home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Contributed / SpriteWorld / SpriteWorld Files / Sources / Scrolling.c < prev    next >
Encoding:
Text File  |  2000-10-06  |  90.1 KB  |  2,772 lines  |  [TEXT/CWIE]

  1. ///--------------------------------------------------------------------------------------
  2. //    Scrolling.c
  3. //
  4. //    By:    Vern Jensen
  5. //    
  6. //    Created: 8/29/95
  7. //
  8. //    Description:    Routines for making fast scrolling games with SpriteWorld
  9. ///--------------------------------------------------------------------------------------
  10.  
  11.  
  12.  
  13. #ifndef __QUICKDRAW__
  14. #include <QuickDraw.h>
  15. #endif
  16.  
  17. #ifndef __MEMORY__
  18. #include <Memory.h>
  19. #endif
  20.  
  21. #ifndef __GESTALT__
  22. #include <Gestalt.h>
  23. #endif
  24.  
  25. #ifndef __SPRITEWORLD__
  26. #include <SpriteWorld.h>
  27. #endif
  28.  
  29. #ifndef __SPRITEWORLDUTILS__
  30. #include <SpriteWorldUtils.h>
  31. #endif
  32.  
  33. #ifndef __BLITPIXIEINTERFACE__
  34. #include <BlitPixieInterface.h>
  35. #endif
  36.  
  37. #ifndef __SCROLLING__
  38. #include <Scrolling.h>
  39. #endif
  40.  
  41. #ifndef __TILING__
  42. #include <Tiling.h>
  43. #endif
  44.  
  45.  
  46. ///--------------------------------------------------------------------------------------
  47. //    SWUpdateScrollingWindow
  48. ///--------------------------------------------------------------------------------------
  49.  
  50. SW_FUNC void SWUpdateScrollingWindow(
  51.     SpriteWorldPtr spriteWorldP)
  52. {
  53.     GWorldPtr        holdGWorld;
  54.     GDHandle        holdGDH;
  55.     
  56.     SW_ASSERT(spriteWorldP != NULL);
  57.     SW_ASSERT(spriteWorldP->workFrameP->isFrameLocked);
  58.     SW_ASSERT(spriteWorldP->windowFrameP->isFrameLocked);
  59.     
  60.     GetGWorld( &holdGWorld, &holdGDH );
  61.     
  62.     SetGWorld(spriteWorldP->windowFrameP->framePort, nil);
  63.     
  64.     if ( spriteWorldP->usingVBL )
  65.     {  
  66.         spriteWorldP->vblTaskRec.hasVBLFired = false;
  67.         while ( !spriteWorldP->vblTaskRec.hasVBLFired )
  68.         {}
  69.     }
  70.     
  71.     gSWCurrentSpriteWorld = spriteWorldP;
  72.     
  73.         // Copy visScrollRect to window
  74.     SWWrapWorkAreaToFrame(spriteWorldP, spriteWorldP->windowFrameP, &spriteWorldP->windRect);
  75.     
  76.     gSWCurrentSpriteWorld = NULL;
  77.                                     
  78.     SetGWorld( holdGWorld, holdGDH );
  79. }
  80.  
  81.  
  82. ///--------------------------------------------------------------------------------------
  83. //    SWUpdateScrollingSpriteWorld - should be called at the beginning of 
  84. //    a scrolling animation, so that idle sprites are set up correctly.
  85. ///--------------------------------------------------------------------------------------
  86.  
  87. SW_FUNC void SWUpdateScrollingSpriteWorld(
  88.     SpriteWorldPtr spriteWorldP,
  89.     Boolean updateWindow)
  90. {
  91.     UpdateRectStructPtr            curRectStructP,
  92.                                 nextRectStructP;
  93.     register SpriteLayerPtr        curSpriteLayerP;
  94.     register SpritePtr            curSpriteP;
  95.     short                        curTileLayer;
  96.     Rect                        *visScrollRectP = &spriteWorldP->visScrollRect;
  97.     Rect                        srcFrameRect, tempDstRect;
  98.     GWorldPtr                    saveGWorld;
  99.     GDHandle                    saveGDH;
  100.     
  101.     SW_ASSERT(spriteWorldP != NULL);
  102.     SW_ASSERT(spriteWorldP->backFrameP->isFrameLocked);
  103.     SW_ASSERT(spriteWorldP->workFrameP->isFrameLocked);
  104.     SW_ASSERT(spriteWorldP->windowFrameP->isFrameLocked);
  105.     
  106.     GetGWorld( &saveGWorld, &saveGDH );
  107.     
  108.     gSWCurrentSpriteWorld = spriteWorldP;
  109.  
  110.         // Copy the background into the work area
  111.     SWSetPortToFrame(spriteWorldP->workFrameP);
  112.     (*spriteWorldP->offscreenDrawProc)(spriteWorldP->backFrameP,
  113.                         spriteWorldP->workFrameP,
  114.                         &spriteWorldP->backFrameP->frameRect,
  115.                         &spriteWorldP->workFrameP->frameRect);
  116.     
  117.             // Call the postEraseCallBack
  118.     if (spriteWorldP->postEraseCallBack != NULL)
  119.         (*spriteWorldP->postEraseCallBack)(spriteWorldP);
  120.  
  121.     
  122.         // Build the current frame of the animation in the work area
  123.     
  124.     curSpriteLayerP = spriteWorldP->headSpriteLayerP;
  125.     curTileLayer = 0;
  126.  
  127.         // iterate through the layers in this world
  128.     while (curSpriteLayerP != NULL)
  129.     {
  130.         curSpriteP = curSpriteLayerP->headSpriteP;
  131.         
  132.         if (curSpriteLayerP->tileLayer > curTileLayer)
  133.             curTileLayer = curSpriteLayerP->tileLayer;
  134.  
  135.             // iterate through the sprites in this layer
  136.         while (curSpriteP != NULL)
  137.         {
  138.             SW_ASSERT(curSpriteP->curFrameP->isFrameLocked);
  139.             curSpriteP->tileDepth = curTileLayer;
  140.             
  141.             if (curSpriteP->isVisible)
  142.             {
  143.                 curSpriteP->destOffscreenRect = curSpriteP->destFrameRect;
  144.                 srcFrameRect = curSpriteP->curFrameP->frameRect;
  145.                     
  146.                     
  147.                     // Clip the sprite's destOffscreenRect with visScrollRect
  148.                     // We use the destOffscreenRect both for drawing and erasing later
  149.                 if (curSpriteP->destOffscreenRect.top < visScrollRectP->top)
  150.                 {
  151.                     srcFrameRect.top += visScrollRectP->top - 
  152.                             curSpriteP->destOffscreenRect.top;
  153.                     curSpriteP->destOffscreenRect.top =  visScrollRectP->top;
  154.                 }
  155.  
  156.                 if (curSpriteP->destOffscreenRect.bottom > visScrollRectP->bottom)
  157.                 {
  158.                     srcFrameRect.bottom += visScrollRectP->bottom - 
  159.                             curSpriteP->destOffscreenRect.bottom;
  160.                     curSpriteP->destOffscreenRect.bottom = visScrollRectP->bottom;
  161.                 }
  162.                 
  163.                 if (curSpriteP->destOffscreenRect.left < visScrollRectP->left)
  164.                 {
  165.                     srcFrameRect.left += visScrollRectP->left - 
  166.                             curSpriteP->destOffscreenRect.left;
  167.                     curSpriteP->destOffscreenRect.left = visScrollRectP->left;
  168.                 }
  169.             
  170.                 if (curSpriteP->destOffscreenRect.right > visScrollRectP->right)
  171.                 {
  172.                     srcFrameRect.right += visScrollRectP->right - 
  173.                             curSpriteP->destOffscreenRect.right;
  174.                     curSpriteP->destOffscreenRect.right = visScrollRectP->right;
  175.                 }
  176.                 
  177.                 curSpriteP->destRectIsVisible =
  178.                         ( (curSpriteP->destOffscreenRect.right >
  179.                         curSpriteP->destOffscreenRect.left) &&
  180.                         (curSpriteP->destOffscreenRect.bottom >
  181.                         curSpriteP->destOffscreenRect.top) );
  182.                 
  183.                 
  184.                     // Is sprite visible on the screen?
  185.                 if (curSpriteP->destRectIsVisible)
  186.                 {
  187.                         // Make the sprite's rect local to the offscreen area
  188.                     curSpriteP->destOffscreenRect.top -= spriteWorldP->vertScrollRectOffset;
  189.                     curSpriteP->destOffscreenRect.bottom -= spriteWorldP->vertScrollRectOffset;
  190.                     curSpriteP->destOffscreenRect.left -= spriteWorldP->horizScrollRectOffset;
  191.                     curSpriteP->destOffscreenRect.right -= spriteWorldP->horizScrollRectOffset;
  192.                     
  193.                     gSWCurrentSpriteBeingDrawn = curSpriteP;
  194.                     
  195.                         // Draw the sprite in the work area
  196.                     SWDrawWrappedSprite(curSpriteP, spriteWorldP->workFrameP,
  197.                         &srcFrameRect, &curSpriteP->destOffscreenRect);
  198.                         
  199.                     gSWCurrentSpriteBeingDrawn = NULL;
  200.                     
  201.                         // Draw tiles above sprite
  202.                     if (spriteWorldP->tilingIsOn &&
  203.                         curSpriteP->tileDepth <= spriteWorldP->lastActiveTileLayer)
  204.                     {
  205.                         tempDstRect = curSpriteP->destOffscreenRect;
  206.                         tempDstRect.top += spriteWorldP->vertScrollRectOffset;
  207.                         tempDstRect.bottom += spriteWorldP->vertScrollRectOffset;
  208.                         tempDstRect.left += spriteWorldP->horizScrollRectOffset;
  209.                         tempDstRect.right += spriteWorldP->horizScrollRectOffset;
  210.                         SWDrawTilesAboveSprite(spriteWorldP, &tempDstRect, curSpriteP->tileDepth);
  211.                     }
  212.                 }
  213.             }
  214.             
  215.                 // Set last rect to current rect
  216.             curSpriteP->oldFrameRect = curSpriteP->destFrameRect;
  217.             curSpriteP->oldRectIsVisible = curSpriteP->destRectIsVisible;
  218.             
  219.             curSpriteP->needsToBeDrawn = false;
  220.             curSpriteP->needsToBeErased = false;
  221.             
  222.             curSpriteP = curSpriteP->nextSpriteP;
  223.         }
  224.         
  225.         curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;
  226.     }
  227.     
  228.     spriteWorldP->oldVisScrollRect = spriteWorldP->visScrollRect;
  229.     
  230.     
  231.             // Call the postDrawCallBack
  232.     if (spriteWorldP->postDrawCallBack != NULL)
  233.         (*spriteWorldP->postDrawCallBack)(spriteWorldP);
  234.  
  235.     
  236.         // Copy the work area to the window
  237.     if (updateWindow)
  238.     {
  239.         SWSetPortToFrame(spriteWorldP->windowFrameP);
  240.  
  241.         if (spriteWorldP->usingVBL)
  242.         {  
  243.             spriteWorldP->vblTaskRec.hasVBLFired = false;
  244.             while ( !spriteWorldP->vblTaskRec.hasVBLFired )
  245.             {}
  246.         }
  247.         
  248.             // Copy visScrollRect to window
  249.         SWWrapWorkAreaToFrame(spriteWorldP, spriteWorldP->windowFrameP, &spriteWorldP->windRect);
  250.     }
  251.     
  252.         // dispose of flagged background rects
  253.     nextRectStructP = spriteWorldP->headUpdateRectP;
  254.     while ( nextRectStructP != NULL )
  255.     {
  256.         curRectStructP = nextRectStructP;
  257.         nextRectStructP = curRectStructP->nextRectStructP;
  258.         DisposePtr( (Ptr)curRectStructP );
  259.     }
  260.     spriteWorldP->headUpdateRectP = NULL;
  261.     
  262.     spriteWorldP->numTilesChanged = 0;
  263.     
  264.     gSWCurrentSpriteWorld = NULL;
  265.     
  266.     SetGWorld( saveGWorld, saveGDH );
  267. }
  268.  
  269.  
  270. ///--------------------------------------------------------------------------------------
  271. //    SWProcessScrollingSpriteWorld
  272. ///--------------------------------------------------------------------------------------
  273.  
  274. SW_FUNC void SWProcessScrollingSpriteWorld(
  275.     SpriteWorldPtr spriteWorldP)
  276. {
  277.         // Process the sprites
  278.     SWProcessSpriteWorld(spriteWorldP);
  279.     if ( !spriteWorldP->frameHasOccurred )
  280.     {
  281.         return;
  282.     }
  283.     
  284.     gSWCurrentSpriteWorld = spriteWorldP;
  285.  
  286.     
  287.         // Call the scrolling world move proc
  288.     if (spriteWorldP->worldMoveProc != NULL)
  289.     {
  290.         (*spriteWorldP->worldMoveProc)(spriteWorldP, spriteWorldP->followSpriteP);
  291.     }
  292.     
  293.     
  294.         // Move visScrollRect
  295.     if (spriteWorldP->horizScrollDelta || spriteWorldP->vertScrollDelta)
  296.     {
  297.         SWOffsetVisScrollRect(spriteWorldP, 
  298.             spriteWorldP->horizScrollDelta, 
  299.             spriteWorldP->vertScrollDelta);
  300.     }
  301.     
  302.     SWProcessNonScrollingLayers(spriteWorldP);
  303.     
  304.     gSWCurrentSpriteWorld = NULL;
  305. }
  306.  
  307.  
  308. ///--------------------------------------------------------------------------------------
  309. //    SWAnimateScrollingSpriteWorld
  310. ///--------------------------------------------------------------------------------------
  311.  
  312. SW_FUNC void SWAnimateScrollingSpriteWorld(
  313.     SpriteWorldPtr spriteWorldP)
  314. {
  315.     UpdateRectStructPtr            curRectStructP,
  316.                                 nextRectStructP;
  317.     register SpriteLayerPtr     curSpriteLayerP;
  318.     register SpritePtr             curSpriteP;
  319.     SpritePtr                     headActiveSpriteP = NULL;    // Tail of active sprite list
  320.     SpritePtr                    headIdleSpriteP = NULL;        // Tail of idle sprite list
  321.     SpritePtr                     curActiveSpriteP = NULL;
  322.     SpritePtr                     curIdleSpriteP = NULL;
  323.     Rect                        *visScrollRectP = &spriteWorldP->visScrollRect;
  324.     Rect                        tempDstRect, tempSrcRect;
  325.     short                        hScrollDelta, vScrollDelta, curTileLayer;
  326.     short                        oldVertScrollRectOffset, oldHorizScrollRectOffset;
  327.     
  328.     SW_ASSERT(spriteWorldP != NULL);
  329.     SW_ASSERT(spriteWorldP->backFrameP->isFrameLocked);
  330.     SW_ASSERT(spriteWorldP->workFrameP->isFrameLocked);
  331.     SW_ASSERT(spriteWorldP->windowFrameP->isFrameLocked);
  332.     
  333.     if (!spriteWorldP->frameHasOccurred)
  334.         return;
  335.     
  336.     gSWCurrentSpriteWorld = spriteWorldP;
  337.     
  338.     oldVertScrollRectOffset = spriteWorldP->backRect.bottom * 
  339.         (spriteWorldP->oldVisScrollRect.top / spriteWorldP->backRect.bottom);
  340.     
  341.     oldHorizScrollRectOffset = spriteWorldP->backRect.right *
  342.         (spriteWorldP->oldVisScrollRect.left / spriteWorldP->backRect.right);
  343.     
  344.     hScrollDelta = visScrollRectP->left - spriteWorldP->oldVisScrollRect.left;
  345.     vScrollDelta = visScrollRectP->top - spriteWorldP->oldVisScrollRect.top;
  346.     
  347.     
  348.             // Add the deadSpriteLayer if there are any Sprites in it.
  349.     if ( spriteWorldP->deadSpriteLayerP->headSpriteP != NULL )
  350.     {
  351.         SWAddSpriteLayer(spriteWorldP, spriteWorldP->deadSpriteLayerP);
  352.     }
  353.     
  354.     
  355.         // Update tiles as we scroll if tiling is turned on
  356.     if (spriteWorldP->tilingIsOn)
  357.     {
  358.             // VisScrollRect moved horizontally
  359.         if (hScrollDelta)
  360.         {
  361.                 // Get rect of new vertical section to update
  362.             tempDstRect = *visScrollRectP;
  363.             
  364.                 // Moved left
  365.             if (hScrollDelta < 0)
  366.             {
  367.                 if (tempDstRect.right > spriteWorldP->oldVisScrollRect.left)
  368.                     tempDstRect.right = spriteWorldP->oldVisScrollRect.left;
  369.             }
  370.             else    // Moved right
  371.             {
  372.                 if (tempDstRect.left < spriteWorldP->oldVisScrollRect.right)
  373.                     tempDstRect.left = spriteWorldP->oldVisScrollRect.right;
  374.             }
  375.     
  376.             (*spriteWorldP->tileRectDrawProc)(spriteWorldP, &tempDstRect, true);
  377.             SWWrapRectToWorkArea(spriteWorldP, &tempDstRect);
  378.             
  379.             
  380.                 // Did VisScrollRect moved diagonally?
  381.             if (vScrollDelta)
  382.             {
  383.                     // Get rect of new horizontal section to update
  384.                 tempDstRect = spriteWorldP->visScrollRect;
  385.                 
  386.                     // Moved up
  387.                 if (vScrollDelta < 0)
  388.                 {
  389.                     if (tempDstRect.bottom > spriteWorldP->oldVisScrollRect.top)
  390.                         tempDstRect.bottom = spriteWorldP->oldVisScrollRect.top;
  391.                 }
  392.                 else    // Moved down
  393.                 {
  394.                     if (tempDstRect.top < spriteWorldP->oldVisScrollRect.bottom)
  395.                         tempDstRect.top = spriteWorldP->oldVisScrollRect.bottom;
  396.                 }
  397.                 
  398.                     // Clip off the part we've already updated
  399.                 if (hScrollDelta < 0)
  400.                 {
  401.                     if (tempDstRect.left < spriteWorldP->oldVisScrollRect.left)
  402.                         tempDstRect.left = spriteWorldP->oldVisScrollRect.left;
  403.                 }
  404.                 else
  405.                 {
  406.                     if (tempDstRect.right > spriteWorldP->oldVisScrollRect.right)
  407.                         tempDstRect.right = spriteWorldP->oldVisScrollRect.right;
  408.                 }
  409.                 
  410.                     // We pass false here to avoid a bug which occured in the
  411.                     // tile optimizing code when updating tiles twice in one frame
  412.                 if (tempDstRect.right > tempDstRect.left)
  413.                 {
  414.                     (*spriteWorldP->tileRectDrawProc)(spriteWorldP, &tempDstRect, false);
  415.                     SWWrapRectToWorkArea(spriteWorldP, &tempDstRect);
  416.                 }
  417.             }
  418.         }        // VisScrollRect moved vertically only
  419.         else if (vScrollDelta)
  420.         {
  421.                 // Get rect of new horizontal section to update
  422.             tempDstRect = *visScrollRectP;
  423.             
  424.                 // Moved up
  425.             if (vScrollDelta < 0)
  426.             {
  427.                 if (tempDstRect.bottom > spriteWorldP->oldVisScrollRect.top)
  428.                     tempDstRect.bottom = spriteWorldP->oldVisScrollRect.top;
  429.             }
  430.             else    // Moved down
  431.             {
  432.                 if (tempDstRect.top < spriteWorldP->oldVisScrollRect.bottom)
  433.                     tempDstRect.top = spriteWorldP->oldVisScrollRect.bottom;
  434.             }
  435.  
  436.             (*spriteWorldP->tileRectDrawProc)(spriteWorldP, &tempDstRect, true);
  437.             SWWrapRectToWorkArea(spriteWorldP, &tempDstRect);
  438.         }
  439.     }
  440.     
  441.     
  442.     //-----------------erase the sprites--------------------
  443.     
  444.         // Set the port to the work area so we can draw in it
  445.     SetGWorld(spriteWorldP->workFrameP->framePort, nil);
  446.     
  447.     curSpriteLayerP = spriteWorldP->headSpriteLayerP;    
  448.     curTileLayer = 0;
  449.     
  450.         // iterate through the layers in this world
  451.     while (curSpriteLayerP != NULL)
  452.     {
  453.         curSpriteP = curSpriteLayerP->headSpriteP;
  454.         
  455.         if (curSpriteLayerP->tileLayer > curTileLayer)
  456.             curTileLayer = curSpriteLayerP->tileLayer;
  457.         
  458.             // iterate through the sprites in this layer
  459.         while (curSpriteP != NULL)
  460.         {
  461.             SW_ASSERT(curSpriteP->curFrameP->isFrameLocked);
  462.             curSpriteP->tileDepth = curTileLayer;
  463.             
  464.                 // Clip the sprite's destOffscreenRect with visScrollRect.
  465.             if (curSpriteP->isVisible)
  466.             {
  467.                 curSpriteP->destOffscreenRect = curSpriteP->destFrameRect;
  468.                 curSpriteP->clippedSourceRect = curSpriteP->curFrameP->frameRect;
  469.                 
  470.  
  471.                 if (curSpriteP->destOffscreenRect.top < visScrollRectP->top)
  472.                 {
  473.                     curSpriteP->clippedSourceRect.top += visScrollRectP->top - 
  474.                             curSpriteP->destOffscreenRect.top;
  475.                     curSpriteP->destOffscreenRect.top = visScrollRectP->top;
  476.                 }
  477.                 
  478.                 if (curSpriteP->destOffscreenRect.bottom > visScrollRectP->bottom)
  479.                 {
  480.                     curSpriteP->clippedSourceRect.bottom += visScrollRectP->bottom - 
  481.                             curSpriteP->destOffscreenRect.bottom;
  482.                     curSpriteP->destOffscreenRect.bottom = visScrollRectP->bottom;
  483.                 }
  484.                 
  485.                 if (curSpriteP->destOffscreenRect.left < visScrollRectP->left)
  486.                 {
  487.                     curSpriteP->clippedSourceRect.left += visScrollRectP->left - 
  488.                             curSpriteP->destOffscreenRect.left;
  489.                     curSpriteP->destOffscreenRect.left = visScrollRectP->left;
  490.                 }
  491.                 
  492.                 if (curSpriteP->destOffscreenRect.right > visScrollRectP->right)
  493.                 {
  494.                     curSpriteP->clippedSourceRect.right += visScrollRectP->right - 
  495.                             curSpriteP->destOffscreenRect.right;
  496.                     curSpriteP->destOffscreenRect.right = visScrollRectP->right;
  497.                 }
  498.                 
  499.                 curSpriteP->destRectIsVisible =
  500.                         (curSpriteP->destOffscreenRect.right >
  501.                         curSpriteP->destOffscreenRect.left &&
  502.                         curSpriteP->destOffscreenRect.bottom >
  503.                         curSpriteP->destOffscreenRect.top);
  504.             }
  505.             
  506.             
  507.                 // Erase the sprites
  508.             if (curSpriteP->needsToBeDrawn && curSpriteP->isVisible ||
  509.                 curSpriteP->needsToBeErased && !curSpriteP->isVisible)
  510.             {
  511.                 // Recalculate the oldOffscreenRect (tempDstRect) from scratch. We can't save the 
  512.                 // destOffscreenRect from the previous frame, since an invisible Sprite that
  513.                 // is made visible many frames later could have an incorrect oldOffscreenRect,
  514.                 // meaning the Sprite would be erased even if it's not currently on the screen.
  515.                 
  516.                 tempDstRect = curSpriteP->oldFrameRect;
  517.                 
  518.                 if (tempDstRect.top < spriteWorldP->oldVisScrollRect.top)
  519.                     tempDstRect.top = spriteWorldP->oldVisScrollRect.top;
  520.                 
  521.                 if (tempDstRect.bottom > spriteWorldP->oldVisScrollRect.bottom)
  522.                     tempDstRect.bottom = spriteWorldP->oldVisScrollRect.bottom;
  523.                 
  524.                 if (tempDstRect.left < spriteWorldP->oldVisScrollRect.left)
  525.                     tempDstRect.left = spriteWorldP->oldVisScrollRect.left;
  526.                 
  527.                 if (tempDstRect.right > spriteWorldP->oldVisScrollRect.right)
  528.                     tempDstRect.right = spriteWorldP->oldVisScrollRect.right;
  529.                 
  530.                     // Was the sprite visible on the screen last frame?
  531.                 if (tempDstRect.right > tempDstRect.left &&
  532.                     tempDstRect.bottom > tempDstRect.top)
  533.                 {
  534.                         // Make the tempDstRect local to the offscreen area
  535.                     tempDstRect.top -= oldVertScrollRectOffset;
  536.                     tempDstRect.bottom -= oldVertScrollRectOffset;
  537.                     tempDstRect.left -= oldHorizScrollRectOffset;
  538.                     tempDstRect.right -= oldHorizScrollRectOffset;
  539.                     
  540.                         // Add sprite to active sprite list
  541.                     if (headActiveSpriteP == NULL)
  542.                         headActiveSpriteP = curSpriteP;
  543.                     
  544.                     if (curActiveSpriteP != NULL)
  545.                         curActiveSpriteP->nextActiveSpriteP = curSpriteP;
  546.                     
  547.                     curActiveSpriteP = curSpriteP;
  548.                     
  549.                     {
  550.                         short temp;
  551.                         
  552.                             // align left edge of tempDstRect for erasing
  553.                         tempDstRect.left &=
  554.                             (spriteWorldP->workFrameP->leftAlignFactor);
  555.                         
  556.                             // align the right edge to long word boundary
  557.                         temp = tempDstRect.right & 
  558.                                 spriteWorldP->workFrameP->rightAlignFactor;
  559.                         if (temp != 0)
  560.                         {
  561.                             tempDstRect.right +=
  562.                                 (spriteWorldP->workFrameP->rightAlignFactor + 1) - temp;
  563.                         }
  564.  
  565.                             // align left edge of oldFrameRect - necessary for
  566.                             // deltaFrameRect below, used by idle sprite collision
  567.                         curSpriteP->oldFrameRect.left &=
  568.                             (spriteWorldP->workFrameP->leftAlignFactor);
  569.                         
  570.                             // align the right edge to long word boundary
  571.                         temp = curSpriteP->oldFrameRect.right &
  572.                             spriteWorldP->workFrameP->rightAlignFactor;
  573.                         if (temp != 0)
  574.                         {
  575.                             curSpriteP->oldFrameRect.right +=
  576.                                 (spriteWorldP->workFrameP->rightAlignFactor + 1) - temp;
  577.                         }
  578.                     }
  579.                     
  580.                         // union last rect and current rect - this is necessary for 
  581.                         // the proper redrawing of idle sprites
  582.                     curSpriteP->deltaFrameRect.top = 
  583.                         SW_MIN(curSpriteP->oldFrameRect.top, curSpriteP->destFrameRect.top);
  584.                     curSpriteP->deltaFrameRect.left = 
  585.                         SW_MIN(curSpriteP->oldFrameRect.left, curSpriteP->destFrameRect.left);
  586.                     curSpriteP->deltaFrameRect.bottom = 
  587.                         SW_MAX(curSpriteP->oldFrameRect.bottom, curSpriteP->destFrameRect.bottom);
  588.                     curSpriteP->deltaFrameRect.right = 
  589.                         SW_MAX(curSpriteP->oldFrameRect.right, curSpriteP->destFrameRect.right);
  590.                     
  591.                     
  592.                         // Erase the sprite from the work area
  593.                     SWEraseWrappedSprite(spriteWorldP, &tempDstRect);
  594.                 }
  595.                 else if (curSpriteP->destRectIsVisible)    // Sprite will be drawn
  596.                 {
  597.                         // Add sprite to active sprite list
  598.                     if (headActiveSpriteP == NULL)
  599.                         headActiveSpriteP = curSpriteP;
  600.                     
  601.                     if (curActiveSpriteP != NULL)
  602.                             curActiveSpriteP->nextActiveSpriteP = curSpriteP;
  603.                     
  604.                     curActiveSpriteP = curSpriteP;
  605.                 }
  606.             }
  607.             else if (curSpriteP->isVisible)        // Visible, idle sprites
  608.             {
  609.                 if (curSpriteP->oldRectIsVisible)
  610.                 {
  611.                         // Is idle sprite moving outside the visScrollRect?
  612.                     if ((hScrollDelta > 0 &&
  613.                         (curSpriteP->destFrameRect.left < visScrollRectP->left) &&
  614.                         (curSpriteP->destFrameRect.right > spriteWorldP->oldVisScrollRect.left)) ||
  615.                         (hScrollDelta < 0 &&
  616.                         (curSpriteP->destFrameRect.left < spriteWorldP->oldVisScrollRect.right) &&
  617.                         (curSpriteP->destFrameRect.right > visScrollRectP->right)) )
  618.                     {
  619.                             // Erase piece of idle sprite outside of visScrollRect
  620.                         tempDstRect = curSpriteP->oldFrameRect;
  621.                         
  622.                             // Get section of sprite outside visScrollRect
  623.                         if (hScrollDelta > 0)
  624.                         {
  625.                             if (tempDstRect.right > visScrollRectP->left)
  626.                                 tempDstRect.right = visScrollRectP->left;
  627.                         }
  628.                         else
  629.                         {
  630.                             if (tempDstRect.left < visScrollRectP->right)
  631.                                 tempDstRect.left = visScrollRectP->right;
  632.                         }
  633.                         
  634.                             // Clip tempDstRect with oldVisScrollRect
  635.                         if (tempDstRect.top < spriteWorldP->oldVisScrollRect.top)
  636.                             tempDstRect.top = spriteWorldP->oldVisScrollRect.top;
  637.                         if (tempDstRect.bottom > spriteWorldP->oldVisScrollRect.bottom)
  638.                             tempDstRect.bottom = spriteWorldP->oldVisScrollRect.bottom;
  639.                         if (tempDstRect.left < spriteWorldP->oldVisScrollRect.left)
  640.                             tempDstRect.left = spriteWorldP->oldVisScrollRect.left;
  641.                         if (tempDstRect.right > spriteWorldP->oldVisScrollRect.right)
  642.                             tempDstRect.right = spriteWorldP->oldVisScrollRect.right;
  643.                         
  644.                             // Make the rect local to the offscreen area
  645.                         tempDstRect.top -= spriteWorldP->vertScrollRectOffset;
  646.                         tempDstRect.bottom -= spriteWorldP->vertScrollRectOffset;
  647.                         tempDstRect.left -= spriteWorldP->horizScrollRectOffset;
  648.                         tempDstRect.right -= spriteWorldP->horizScrollRectOffset;
  649.                         
  650.                         SWEraseWrappedSprite(spriteWorldP, &tempDstRect);
  651.                     }
  652.                     
  653.                         // Is idle sprite moving outside the visScrollRect?
  654.                     if ((vScrollDelta > 0 &&
  655.                         (curSpriteP->destFrameRect.top < visScrollRectP->top) &&
  656.                         (curSpriteP->destFrameRect.bottom > spriteWorldP->oldVisScrollRect.top)) ||
  657.                         (vScrollDelta < 0 &&
  658.                         (curSpriteP->destFrameRect.top < spriteWorldP->oldVisScrollRect.bottom) &&
  659.                         (curSpriteP->destFrameRect.bottom > visScrollRectP->bottom)) )
  660.                     {
  661.                             // Erase piece of idle sprite outside of visScrollRect
  662.                         tempDstRect = curSpriteP->oldFrameRect;
  663.                         
  664.                             // Get section of sprite outside visScrollRect
  665.                         if (vScrollDelta > 0)
  666.                         {
  667.                             if (tempDstRect.bottom > visScrollRectP->top)
  668.                                 tempDstRect.bottom = visScrollRectP->top;
  669.                         }
  670.                         else
  671.                         {
  672.                             if (tempDstRect.top < visScrollRectP->bottom)
  673.                                 tempDstRect.top = visScrollRectP->bottom;
  674.                         }
  675.                         
  676.                             // Clip tempDstRect with oldVisScrollRect
  677.                         if (tempDstRect.top < spriteWorldP->oldVisScrollRect.top)
  678.                             tempDstRect.top = spriteWorldP->oldVisScrollRect.top;
  679.                         if (tempDstRect.bottom > spriteWorldP->oldVisScrollRect.bottom)
  680.                             tempDstRect.bottom = spriteWorldP->oldVisScrollRect.bottom;
  681.                         if (tempDstRect.left < spriteWorldP->oldVisScrollRect.left)
  682.                             tempDstRect.left = spriteWorldP->oldVisScrollRect.left;
  683.                         if (tempDstRect.right > spriteWorldP->oldVisScrollRect.right)
  684.                             tempDstRect.right = spriteWorldP->oldVisScrollRect.right;
  685.                         
  686.                             // Make the rect local to the offscreen area
  687.                         tempDstRect.top -= spriteWorldP->vertScrollRectOffset;
  688.                         tempDstRect.bottom -= spriteWorldP->vertScrollRectOffset;
  689.                         tempDstRect.left -= spriteWorldP->horizScrollRectOffset;
  690.                         tempDstRect.right -= spriteWorldP->horizScrollRectOffset;
  691.                         
  692.                         SWEraseWrappedSprite(spriteWorldP, &tempDstRect);
  693.                     }
  694.                 }
  695.                             
  696.                 
  697.                     // Is the idle sprite visible on the screen?
  698.                 if (curSpriteP->destRectIsVisible)
  699.                 {
  700.                         // Add sprite to idle sprite list
  701.                     if (headIdleSpriteP == NULL)
  702.                         headIdleSpriteP = curSpriteP;
  703.                     
  704.                     if (curIdleSpriteP != NULL)
  705.                         curIdleSpriteP->nextIdleSpriteP = curSpriteP;
  706.                     
  707.                     curIdleSpriteP = curSpriteP;
  708.                 }
  709.             }
  710.  
  711.             curSpriteP = curSpriteP->nextSpriteP;
  712.         }
  713.  
  714.         curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;    
  715.     }
  716.     
  717.     if (curActiveSpriteP != NULL)
  718.         curActiveSpriteP->nextActiveSpriteP = NULL;
  719.     
  720.     if (curIdleSpriteP != NULL)
  721.         curIdleSpriteP->nextIdleSpriteP = NULL;
  722.     
  723.  
  724.     
  725.         // This section of code iterates through the idle sprite list, drawing the tiny
  726.         // sliver of any idle sprites that have just entered the visScrollRect.
  727.     curIdleSpriteP = headIdleSpriteP;
  728.     while (curIdleSpriteP != NULL)
  729.     {
  730.             // Draw vertical piece of idle sprite if it is coming into the visScrollRect.
  731.         if ((vScrollDelta > 0 &&
  732.             (curIdleSpriteP->destFrameRect.top < visScrollRectP->bottom) &&
  733.             (curIdleSpriteP->destFrameRect.bottom > spriteWorldP->oldVisScrollRect.bottom) ) ||
  734.             (vScrollDelta < 0 &&
  735.             (curIdleSpriteP->destFrameRect.top < spriteWorldP->oldVisScrollRect.top) &&
  736.             (curIdleSpriteP->destFrameRect.bottom > visScrollRectP->top)) )
  737.         {
  738.             tempDstRect = curIdleSpriteP->destOffscreenRect;
  739.             tempSrcRect = curIdleSpriteP->clippedSourceRect;
  740.             
  741.                 // Determine whether scrolling up or down, then get 
  742.                 // section of sprite outside oldVisScrollRect.
  743.             if (vScrollDelta < 0)
  744.             {
  745.                     // Scrolling up, so get section above oldVisScrollRect
  746.                 if (tempDstRect.bottom > spriteWorldP->oldVisScrollRect.top)
  747.                 {
  748.                     tempSrcRect.bottom += spriteWorldP->oldVisScrollRect.top - 
  749.                         tempDstRect.bottom;
  750.                     tempDstRect.bottom = spriteWorldP->oldVisScrollRect.top;
  751.                 }
  752.             }
  753.             else
  754.             {
  755.                     // Scrolling down, so get section below oldVisScrollRect
  756.                 if (tempDstRect.top < spriteWorldP->oldVisScrollRect.bottom)
  757.                 {
  758.                     tempSrcRect.top += spriteWorldP->oldVisScrollRect.bottom - 
  759.                         tempDstRect.top;
  760.                     tempDstRect.top = spriteWorldP->oldVisScrollRect.bottom;
  761.                 }
  762.             }
  763.             
  764.                 // Make the sprite's rect local to the offscreen area
  765.             tempDstRect.top -= spriteWorldP->vertScrollRectOffset;
  766.             tempDstRect.bottom -= spriteWorldP->vertScrollRectOffset;
  767.             tempDstRect.left -= spriteWorldP->horizScrollRectOffset;
  768.             tempDstRect.right -= spriteWorldP->horizScrollRectOffset;
  769.  
  770.                 // Draw the sprite in the work area
  771.             SWDrawWrappedSprite(curIdleSpriteP, spriteWorldP->workFrameP,
  772.                     &tempSrcRect, &tempDstRect);
  773.             
  774.                 // Draw tiles above sprite
  775.             if (spriteWorldP->tilingIsOn &&
  776.                 curIdleSpriteP->tileDepth <= spriteWorldP->lastActiveTileLayer)
  777.             {
  778.                 tempDstRect.top += spriteWorldP->vertScrollRectOffset;
  779.                 tempDstRect.bottom += spriteWorldP->vertScrollRectOffset;
  780.                 tempDstRect.left += spriteWorldP->horizScrollRectOffset;
  781.                 tempDstRect.right += spriteWorldP->horizScrollRectOffset;
  782.                 SWDrawTilesAboveSprite(spriteWorldP, &tempDstRect, curIdleSpriteP->tileDepth);
  783.             }
  784.         }
  785.         
  786.         
  787.             // Draw horizontal piece of idle sprite if it is coming into the visScrollRect.
  788.         if ((hScrollDelta > 0 &&
  789.             (curIdleSpriteP->destFrameRect.left < visScrollRectP->right) &&
  790.             (curIdleSpriteP->destFrameRect.right > spriteWorldP->oldVisScrollRect.right) ) ||
  791.             (hScrollDelta < 0 &&
  792.             (curIdleSpriteP->destFrameRect.left < spriteWorldP->oldVisScrollRect.left) &&
  793.             (curIdleSpriteP->destFrameRect.right > visScrollRectP->left)) )
  794.         {
  795.             tempDstRect = curIdleSpriteP->destOffscreenRect;
  796.             tempSrcRect = curIdleSpriteP->clippedSourceRect;
  797.             
  798.                 // Determine whether scrolling left or right, then get 
  799.                 // section of sprite outside oldVisScrollRect.
  800.             if (hScrollDelta < 0)
  801.             {
  802.                     // Scrolling left, so get section to the left of oldVisScrollRect
  803.                 if (tempDstRect.right > spriteWorldP->oldVisScrollRect.left)
  804.                 {
  805.                     tempSrcRect.right += spriteWorldP->oldVisScrollRect.left - 
  806.                         tempDstRect.right;
  807.                     tempDstRect.right = spriteWorldP->oldVisScrollRect.left;
  808.                 }
  809.             }
  810.             else
  811.             {
  812.                     // Scrolling right, so get section to the right of oldVisScrollRect
  813.                 if (tempDstRect.left < spriteWorldP->oldVisScrollRect.right)
  814.                 {
  815.                     tempSrcRect.left += spriteWorldP->oldVisScrollRect.right - 
  816.                         tempDstRect.left;
  817.                     tempDstRect.left = spriteWorldP->oldVisScrollRect.right;
  818.                 }
  819.             }
  820.             
  821.             
  822.                 // Make the sprite's rect local to the offscreen area
  823.             tempDstRect.top -= spriteWorldP->vertScrollRectOffset;
  824.             tempDstRect.bottom -= spriteWorldP->vertScrollRectOffset;
  825.             tempDstRect.left -= spriteWorldP->horizScrollRectOffset;
  826.             tempDstRect.right -= spriteWorldP->horizScrollRectOffset;
  827.  
  828.                 // Draw the sprite in the work area
  829.             SWDrawWrappedSprite(curIdleSpriteP, spriteWorldP->workFrameP,
  830.                     &tempSrcRect, &tempDstRect);
  831.             
  832.                 // Draw tiles above sprite
  833.             if (spriteWorldP->tilingIsOn &&
  834.                 curIdleSpriteP->tileDepth <= spriteWorldP->lastActiveTileLayer)
  835.             {
  836.                 tempDstRect.top += spriteWorldP->vertScrollRectOffset;
  837.                 tempDstRect.bottom += spriteWorldP->vertScrollRectOffset;
  838.                 tempDstRect.left += spriteWorldP->horizScrollRectOffset;
  839.                 tempDstRect.right += spriteWorldP->horizScrollRectOffset;
  840.                 SWDrawTilesAboveSprite(spriteWorldP, &tempDstRect, curIdleSpriteP->tileDepth);
  841.             }
  842.         }
  843.     
  844.         curIdleSpriteP = curIdleSpriteP->nextIdleSpriteP;
  845.     }
  846.     
  847.  
  848.         // update flagged background rects
  849.     curRectStructP = spriteWorldP->headUpdateRectP;
  850.     while ( curRectStructP != NULL )
  851.     {
  852.         tempDstRect = curRectStructP->updateRect;
  853.         
  854.             // Make the rect local to the offscreen area
  855.         tempDstRect.top -= spriteWorldP->vertScrollRectOffset;
  856.         tempDstRect.bottom -= spriteWorldP->vertScrollRectOffset;
  857.         tempDstRect.left -= spriteWorldP->horizScrollRectOffset;
  858.         tempDstRect.right -= spriteWorldP->horizScrollRectOffset;
  859.         
  860.             // We're not really erasing a sprite, just copying while wrapping
  861.         SWEraseWrappedSprite(spriteWorldP, &tempDstRect);
  862.         curRectStructP = curRectStructP->nextRectStructP;
  863.     }
  864.     
  865.         // Redraw idle sprites that were erased by a tile
  866.     if (spriteWorldP->numTilesChanged > 0)
  867.         SWCheckWrappedIdleSpritesWithTiles(spriteWorldP, headIdleSpriteP);
  868.  
  869.         // Redraw idle sprites that were erased by an updateRect
  870.     if (spriteWorldP->headUpdateRectP != NULL)
  871.         SWCheckWrappedIdleSpritesWithRects(spriteWorldP, headIdleSpriteP);
  872.     
  873.         // Call the postEraseCallBack
  874.     if (spriteWorldP->postEraseCallBack != NULL)
  875.         (*spriteWorldP->postEraseCallBack)(spriteWorldP);
  876.  
  877.  
  878.     //-----------------draw the sprites-------------------
  879.  
  880.     curSpriteLayerP = spriteWorldP->headSpriteLayerP;
  881.  
  882.         // iterate through the layers in this world
  883.     while (curSpriteLayerP != NULL)
  884.     {
  885.         curSpriteP = curSpriteLayerP->headSpriteP;
  886.  
  887.             // iterate through the sprites in this layer
  888.         while (curSpriteP != NULL)
  889.         {
  890.             if (curSpriteP->isVisible)
  891.             {
  892.                     // Make the sprite's rect local to the offscreen area
  893.                 curSpriteP->destOffscreenRect.top -= spriteWorldP->vertScrollRectOffset;
  894.                 curSpriteP->destOffscreenRect.bottom -= spriteWorldP->vertScrollRectOffset;
  895.                 curSpriteP->destOffscreenRect.left -= spriteWorldP->horizScrollRectOffset;
  896.                 curSpriteP->destOffscreenRect.right -= spriteWorldP->horizScrollRectOffset;
  897.                 
  898.                 if (curSpriteP->needsToBeDrawn)
  899.                 {
  900.                         // Is the sprite visible on the screen?
  901.                     if (curSpriteP->destRectIsVisible)
  902.                     {
  903.                         gSWCurrentSpriteBeingDrawn = curSpriteP;
  904.                         
  905.                             // Draw the sprite in the work area
  906.                         SWDrawWrappedSprite(curSpriteP, spriteWorldP->workFrameP,
  907.                             &curSpriteP->clippedSourceRect, 
  908.                             &curSpriteP->destOffscreenRect);
  909.                         
  910.                         gSWCurrentSpriteBeingDrawn = NULL;
  911.                         
  912.                             // Draw tiles above sprite
  913.                         if (spriteWorldP->tilingIsOn &&
  914.                             curSpriteP->tileDepth <= spriteWorldP->lastActiveTileLayer)
  915.                         {
  916.                             tempDstRect = curSpriteP->destOffscreenRect;
  917.                             tempDstRect.top += spriteWorldP->vertScrollRectOffset;
  918.                             tempDstRect.bottom += spriteWorldP->vertScrollRectOffset;
  919.                             tempDstRect.left += spriteWorldP->horizScrollRectOffset;
  920.                             tempDstRect.right += spriteWorldP->horizScrollRectOffset;
  921.                             SWDrawTilesAboveSprite(spriteWorldP, &tempDstRect, curSpriteP->tileDepth);
  922.                         }
  923.                     }
  924.                 }
  925.                 else
  926.                 {
  927.                         // Is the idle sprite visible on the screen?
  928.                     if (curSpriteP->destRectIsVisible)
  929.                     {
  930.                         SWCheckWrappedIdleSpriteOverlap(spriteWorldP, 
  931.                             curSpriteP, headActiveSpriteP);
  932.                     }
  933.                 }
  934.             }
  935.             
  936.                 // Set last rect to current rect
  937.             curSpriteP->oldFrameRect = curSpriteP->destFrameRect;
  938.             curSpriteP->oldRectIsVisible = curSpriteP->destRectIsVisible;
  939.             
  940.             curSpriteP->needsToBeDrawn = false;
  941.             curSpriteP->needsToBeErased = false;
  942.  
  943.             curSpriteP = curSpriteP->nextSpriteP;
  944.         }
  945.         
  946.         curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;
  947.     }
  948.     
  949.     spriteWorldP->oldVisScrollRect = spriteWorldP->visScrollRect;
  950.     
  951.     
  952.             // Call the postDrawCallBack
  953.     if (spriteWorldP->postDrawCallBack != NULL)
  954.         (*spriteWorldP->postDrawCallBack)(spriteWorldP);
  955.     
  956.     
  957.     //-----------------update the screen--------------------
  958.     
  959.         // Set the port to the window
  960.     SetGWorld(spriteWorldP->windowFrameP->framePort, nil);
  961.     
  962.     if (spriteWorldP->usingVBL)
  963.     {  
  964.         spriteWorldP->vblTaskRec.hasVBLFired = false;
  965.         while ( !spriteWorldP->vblTaskRec.hasVBLFired )
  966.         {}
  967.     }
  968.     
  969.         // Copy offscreen area to screen while wrapping
  970.     SWWrapWorkAreaToFrame(spriteWorldP, spriteWorldP->windowFrameP, &spriteWorldP->windRect);
  971.     
  972.     
  973.             // dispose of flagged background rects
  974.     nextRectStructP = spriteWorldP->headUpdateRectP;
  975.     while ( nextRectStructP != NULL )
  976.     {
  977.         curRectStructP = nextRectStructP;
  978.         nextRectStructP = curRectStructP->nextRectStructP;
  979.         DisposePtr( (Ptr)curRectStructP );
  980.     }
  981.     spriteWorldP->headUpdateRectP = NULL;
  982.     
  983.     spriteWorldP->numTilesChanged = 0;
  984.     
  985.     gSWCurrentSpriteWorld = NULL;
  986.     
  987.         // Remove the deadSpriteLayer if we added it earlier.
  988.     if ( spriteWorldP->deadSpriteLayerP->headSpriteP != NULL )
  989.     {
  990.         SWRemoveSpriteLayer(spriteWorldP, spriteWorldP->deadSpriteLayerP);
  991.     }
  992. }
  993.  
  994.  
  995. ///--------------------------------------------------------------------------------------
  996. //    SWFastAnimateScrollingSpriteWorld - essentially the same as SWAnimateScrollingSpriteWorld,
  997. //    except that this only updates that sprites/tiles that have moved or changed, by calling
  998. //    SWWrapRectToScreen. All code that handles updating tiles/sprites while scrolling has
  999. //    been removed. (Three parts: the part that draws new tiles, the part that erases idle
  1000. //    sprites leaving the visScrollRect, and the part that draws idle sprites entering it.)
  1001. ///--------------------------------------------------------------------------------------
  1002.  
  1003. SW_FUNC void SWFastAnimateScrollingSpriteWorld(
  1004.     SpriteWorldPtr spriteWorldP)
  1005. {
  1006.     UpdateRectStructPtr            curRectStructP,
  1007.                                 nextRectStructP;
  1008.     register SpriteLayerPtr     curSpriteLayerP;
  1009.     register SpritePtr             curSpriteP;
  1010.     SpritePtr                     headActiveSpriteP = NULL;    // Tail of active sprite list
  1011.     SpritePtr                    headIdleSpriteP = NULL;        // Tail of idle sprite list
  1012.     SpritePtr                     curActiveSpriteP = NULL;
  1013.     SpritePtr                     curIdleSpriteP = NULL;
  1014.     Rect                        *visScrollRectP = &spriteWorldP->visScrollRect;
  1015.     Rect                        tempDstRect;
  1016.     Rect                        *changedRectP;
  1017.     short                        hScrollDelta, vScrollDelta, curTileLayer, index;
  1018.     short                        oldVertScrollRectOffset, oldHorizScrollRectOffset;
  1019.     
  1020.     SW_ASSERT(spriteWorldP != NULL);
  1021.     SW_ASSERT(spriteWorldP->backFrameP->isFrameLocked);
  1022.     SW_ASSERT(spriteWorldP->workFrameP->isFrameLocked);
  1023.     SW_ASSERT(spriteWorldP->windowFrameP->isFrameLocked);
  1024.     
  1025.     if (!spriteWorldP->frameHasOccurred)
  1026.         return;
  1027.         
  1028.     gSWCurrentSpriteWorld = spriteWorldP;
  1029.     
  1030.     oldVertScrollRectOffset = spriteWorldP->backRect.bottom * 
  1031.         (spriteWorldP->oldVisScrollRect.top / spriteWorldP->backRect.bottom);
  1032.     
  1033.     oldHorizScrollRectOffset = spriteWorldP->backRect.right *
  1034.         (spriteWorldP->oldVisScrollRect.left / spriteWorldP->backRect.right);
  1035.         
  1036.     hScrollDelta = visScrollRectP->left - spriteWorldP->oldVisScrollRect.left;
  1037.     vScrollDelta = visScrollRectP->top - spriteWorldP->oldVisScrollRect.top;
  1038.     if (hScrollDelta || vScrollDelta)
  1039.     {
  1040.             // We let this function do everything when scrolling
  1041.         SWAnimateScrollingSpriteWorld(spriteWorldP);
  1042.         return;
  1043.     }
  1044.     
  1045.     
  1046.         // Add the deadSpriteLayer if there are any Sprites in it.
  1047.     if ( spriteWorldP->deadSpriteLayerP->headSpriteP != NULL )
  1048.     {
  1049.         SWAddSpriteLayer(spriteWorldP, spriteWorldP->deadSpriteLayerP);
  1050.     }
  1051.     
  1052.     
  1053.     //-----------------erase the sprites--------------------
  1054.     
  1055.         // Set the port to the work area so we can draw in it
  1056.     SetGWorld(spriteWorldP->workFrameP->framePort, nil);
  1057.     
  1058.     curSpriteLayerP = spriteWorldP->headSpriteLayerP;
  1059.     curTileLayer = 0;
  1060.     
  1061.         // iterate through the layers in this world
  1062.     while (curSpriteLayerP != NULL)
  1063.     {
  1064.         curSpriteP = curSpriteLayerP->headSpriteP;
  1065.         
  1066.         if (curSpriteLayerP->tileLayer > curTileLayer)
  1067.             curTileLayer = curSpriteLayerP->tileLayer;
  1068.         
  1069.             // iterate through the sprites in this layer
  1070.         while (curSpriteP != NULL)
  1071.         {
  1072.             SW_ASSERT(curSpriteP->curFrameP->isFrameLocked);
  1073.             curSpriteP->tileDepth = curTileLayer;
  1074.             
  1075.                 // Clip the sprite's destOffscreenRect with visScrollRect.
  1076.             if (curSpriteP->isVisible)
  1077.             {
  1078.                 curSpriteP->destOffscreenRect = curSpriteP->destFrameRect;
  1079.                 curSpriteP->clippedSourceRect = curSpriteP->curFrameP->frameRect;
  1080.                 
  1081.  
  1082.                 if (curSpriteP->destOffscreenRect.top < visScrollRectP->top)
  1083.                 {
  1084.                     curSpriteP->clippedSourceRect.top += visScrollRectP->top - 
  1085.                             curSpriteP->destOffscreenRect.top;
  1086.                     curSpriteP->destOffscreenRect.top = visScrollRectP->top;
  1087.                 }
  1088.                 
  1089.                 if (curSpriteP->destOffscreenRect.bottom > visScrollRectP->bottom)
  1090.                 {
  1091.                     curSpriteP->clippedSourceRect.bottom += visScrollRectP->bottom - 
  1092.                             curSpriteP->destOffscreenRect.bottom;
  1093.                     curSpriteP->destOffscreenRect.bottom = visScrollRectP->bottom;
  1094.                 }
  1095.                 
  1096.                 if (curSpriteP->destOffscreenRect.left < visScrollRectP->left)
  1097.                 {
  1098.                     curSpriteP->clippedSourceRect.left += visScrollRectP->left - 
  1099.                             curSpriteP->destOffscreenRect.left;
  1100.                     curSpriteP->destOffscreenRect.left = visScrollRectP->left;
  1101.                 }
  1102.                 
  1103.                 if (curSpriteP->destOffscreenRect.right > visScrollRectP->right)
  1104.                 {
  1105.                     curSpriteP->clippedSourceRect.right += visScrollRectP->right - 
  1106.                             curSpriteP->destOffscreenRect.right;
  1107.                     curSpriteP->destOffscreenRect.right = visScrollRectP->right;
  1108.                 }
  1109.                 
  1110.                 curSpriteP->destRectIsVisible =
  1111.                         (curSpriteP->destOffscreenRect.right >
  1112.                         curSpriteP->destOffscreenRect.left &&
  1113.                         curSpriteP->destOffscreenRect.bottom >
  1114.                         curSpriteP->destOffscreenRect.top);
  1115.             }
  1116.             
  1117.             
  1118.                 // Erase the sprites
  1119.             if (curSpriteP->needsToBeDrawn && curSpriteP->isVisible ||
  1120.                 curSpriteP->needsToBeErased && !curSpriteP->isVisible)
  1121.             {
  1122.                 // Recalculate the oldOffscreenRect (tempDstRect) from scratch. We can't save the 
  1123.                 // destOffscreenRect from the previous frame, since an invisible Sprite that
  1124.                 // is made visible many frames later could have an incorrect oldOffscreenRect,
  1125.                 // meaning the Sprite would be erased even if it's not currently on the screen.
  1126.                 
  1127.                 tempDstRect = curSpriteP->oldFrameRect;
  1128.                 
  1129.                 if (tempDstRect.top < spriteWorldP->oldVisScrollRect.top)
  1130.                     tempDstRect.top = spriteWorldP->oldVisScrollRect.top;
  1131.                 
  1132.                 if (tempDstRect.bottom > spriteWorldP->oldVisScrollRect.bottom)
  1133.                     tempDstRect.bottom = spriteWorldP->oldVisScrollRect.bottom;
  1134.                 
  1135.                 if (tempDstRect.left < spriteWorldP->oldVisScrollRect.left)
  1136.                     tempDstRect.left = spriteWorldP->oldVisScrollRect.left;
  1137.                 
  1138.                 if (tempDstRect.right > spriteWorldP->oldVisScrollRect.right)
  1139.                     tempDstRect.right = spriteWorldP->oldVisScrollRect.right;
  1140.                 
  1141.                     // Was the sprite visible on the screen last frame?
  1142.                 if (tempDstRect.right > tempDstRect.left &&
  1143.                     tempDstRect.bottom > tempDstRect.top)
  1144.                 {
  1145.                         // Make the tempDstRect local to the offscreen area
  1146.                     tempDstRect.top -= oldVertScrollRectOffset;
  1147.                     tempDstRect.bottom -= oldVertScrollRectOffset;
  1148.                     tempDstRect.left -= oldHorizScrollRectOffset;
  1149.                     tempDstRect.right -= oldHorizScrollRectOffset;
  1150.  
  1151.                         // Add sprite to active sprite list
  1152.                     if (headActiveSpriteP == NULL)
  1153.                         headActiveSpriteP = curSpriteP;
  1154.                     
  1155.                     if (curActiveSpriteP != NULL)
  1156.                             curActiveSpriteP->nextActiveSpriteP = curSpriteP;
  1157.                     
  1158.                     curActiveSpriteP = curSpriteP;
  1159.                     
  1160.                     {
  1161.                         short temp;
  1162.                         
  1163.                             // align left edge of tempDstRect for erasing
  1164.                         tempDstRect.left &=
  1165.                             (spriteWorldP->workFrameP->leftAlignFactor);
  1166.                         
  1167.                             // align the right edge to long word boundary
  1168.                         temp = tempDstRect.right &
  1169.                             spriteWorldP->workFrameP->rightAlignFactor;
  1170.                         if (temp != 0)
  1171.                         {
  1172.                             tempDstRect.right +=
  1173.                                 (spriteWorldP->workFrameP->rightAlignFactor + 1) - temp;
  1174.                         }
  1175.  
  1176.                             // align left edge of oldFrameRect - necessary for
  1177.                             // deltaFrameRect below, used by idle sprite collision
  1178.                         curSpriteP->oldFrameRect.left &=
  1179.                             (spriteWorldP->workFrameP->leftAlignFactor);
  1180.                         
  1181.                             // align the right edge to long word boundary
  1182.                         temp = curSpriteP->oldFrameRect.right &
  1183.                             spriteWorldP->workFrameP->rightAlignFactor;
  1184.                         if (temp != 0)
  1185.                         {
  1186.                             curSpriteP->oldFrameRect.right +=
  1187.                                 (spriteWorldP->workFrameP->rightAlignFactor + 1) - temp;
  1188.                         }
  1189.                     }
  1190.                     
  1191.                         // union last rect and current rect - this is necessary for 
  1192.                         // the proper redrawing of idle sprites
  1193.                     curSpriteP->deltaFrameRect.top = 
  1194.                         SW_MIN(curSpriteP->oldFrameRect.top, curSpriteP->destFrameRect.top);
  1195.                     curSpriteP->deltaFrameRect.left = 
  1196.                         SW_MIN(curSpriteP->oldFrameRect.left, curSpriteP->destFrameRect.left);
  1197.                     curSpriteP->deltaFrameRect.bottom = 
  1198.                         SW_MAX(curSpriteP->oldFrameRect.bottom, curSpriteP->destFrameRect.bottom);
  1199.                     curSpriteP->deltaFrameRect.right = 
  1200.                         SW_MAX(curSpriteP->oldFrameRect.right, curSpriteP->destFrameRect.right);
  1201.                     
  1202.                     
  1203.                         // Erase the sprite from the work area
  1204.                     SWEraseWrappedSprite(spriteWorldP, &tempDstRect);
  1205.                 }
  1206.                 else if (curSpriteP->destRectIsVisible)    // Sprite will be drawn
  1207.                 {
  1208.                         // Add sprite to active sprite list
  1209.                     if (headActiveSpriteP == NULL)
  1210.                         headActiveSpriteP = curSpriteP;
  1211.                     
  1212.                     if (curActiveSpriteP != NULL)
  1213.                             curActiveSpriteP->nextActiveSpriteP = curSpriteP;
  1214.                     
  1215.                     curActiveSpriteP = curSpriteP;
  1216.                 }
  1217.             }
  1218.             else if (curSpriteP->isVisible)        // Visible, idle sprites
  1219.             {
  1220.                     // Is the idle sprite visible on the screen?
  1221.                 if (curSpriteP->destRectIsVisible)
  1222.                 {
  1223.                         // Add sprite to idle sprite list
  1224.                     if (headIdleSpriteP == NULL)
  1225.                         headIdleSpriteP = curSpriteP;
  1226.                     
  1227.                     if (curIdleSpriteP != NULL)
  1228.                         curIdleSpriteP->nextIdleSpriteP = curSpriteP;
  1229.                     
  1230.                     curIdleSpriteP = curSpriteP;
  1231.                 }
  1232.             }
  1233.  
  1234.             curSpriteP = curSpriteP->nextSpriteP;
  1235.         }
  1236.  
  1237.         curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;    
  1238.     }
  1239.     
  1240.     if (curActiveSpriteP != NULL)
  1241.         curActiveSpriteP->nextActiveSpriteP = NULL;
  1242.     
  1243.     if (curIdleSpriteP != NULL)
  1244.         curIdleSpriteP->nextIdleSpriteP = NULL;
  1245.         
  1246.  
  1247.         // update flagged background rects
  1248.     curRectStructP = spriteWorldP->headUpdateRectP;
  1249.     while ( curRectStructP != NULL )
  1250.     {
  1251.         tempDstRect = curRectStructP->updateRect;
  1252.         
  1253.             // Make the rect local to the offscreen area
  1254.         tempDstRect.top -= spriteWorldP->vertScrollRectOffset;
  1255.         tempDstRect.bottom -= spriteWorldP->vertScrollRectOffset;
  1256.         tempDstRect.left -= spriteWorldP->horizScrollRectOffset;
  1257.         tempDstRect.right -= spriteWorldP->horizScrollRectOffset;
  1258.         
  1259.             // We're not really erasing a sprite, just copying while wrapping
  1260.         SWEraseWrappedSprite(spriteWorldP, &tempDstRect);
  1261.         curRectStructP = curRectStructP->nextRectStructP;
  1262.     }
  1263.     
  1264.         // Redraw idle sprites that were erased by a tile
  1265.     if (spriteWorldP->numTilesChanged > 0)
  1266.         SWCheckWrappedIdleSpritesWithTiles(spriteWorldP, headIdleSpriteP);
  1267.  
  1268.         // Redraw idle sprites that were erased by an updateRect
  1269.     if (spriteWorldP->headUpdateRectP != NULL)
  1270.         SWCheckWrappedIdleSpritesWithRects(spriteWorldP, headIdleSpriteP);
  1271.     
  1272.         // Call the postEraseCallBack
  1273.     if (spriteWorldP->postEraseCallBack != NULL)
  1274.         (*spriteWorldP->postEraseCallBack)(spriteWorldP);
  1275.  
  1276.  
  1277.     //-----------------draw the sprites-------------------
  1278.  
  1279.     curSpriteLayerP = spriteWorldP->headSpriteLayerP;
  1280.  
  1281.         // iterate through the layers in this world
  1282.     while (curSpriteLayerP != NULL)
  1283.     {
  1284.         curSpriteP = curSpriteLayerP->headSpriteP;
  1285.  
  1286.             // iterate through the sprites in this layer
  1287.         while (curSpriteP != NULL)
  1288.         {
  1289.             if (curSpriteP->isVisible)
  1290.             {
  1291.                     // Make the sprite's rect local to the offscreen area
  1292.                 curSpriteP->destOffscreenRect.top -= spriteWorldP->vertScrollRectOffset;
  1293.                 curSpriteP->destOffscreenRect.bottom -= spriteWorldP->vertScrollRectOffset;
  1294.                 curSpriteP->destOffscreenRect.left -= spriteWorldP->horizScrollRectOffset;
  1295.                 curSpriteP->destOffscreenRect.right -= spriteWorldP->horizScrollRectOffset;
  1296.                 
  1297.                 if (curSpriteP->needsToBeDrawn)
  1298.                 {
  1299.                         // Is the sprite visible on the screen?
  1300.                     if (curSpriteP->destRectIsVisible)
  1301.                     {
  1302.                         gSWCurrentSpriteBeingDrawn = curSpriteP;
  1303.                         
  1304.                             // Draw the sprite in the work area
  1305.                         SWDrawWrappedSprite(curSpriteP, spriteWorldP->workFrameP,
  1306.                             &curSpriteP->clippedSourceRect, 
  1307.                             &curSpriteP->destOffscreenRect);
  1308.                         
  1309.                         gSWCurrentSpriteBeingDrawn = NULL;
  1310.                         
  1311.                             // Draw tiles above sprite
  1312.                         if (spriteWorldP->tilingIsOn &&
  1313.                             curSpriteP->tileDepth <= spriteWorldP->lastActiveTileLayer)
  1314.                         {
  1315.                             tempDstRect = curSpriteP->destOffscreenRect;
  1316.                             tempDstRect.top += spriteWorldP->vertScrollRectOffset;
  1317.                             tempDstRect.bottom += spriteWorldP->vertScrollRectOffset;
  1318.                             tempDstRect.left += spriteWorldP->horizScrollRectOffset;
  1319.                             tempDstRect.right += spriteWorldP->horizScrollRectOffset;
  1320.                             SWDrawTilesAboveSprite(spriteWorldP, &tempDstRect, curSpriteP->tileDepth);
  1321.                         }
  1322.                     }
  1323.                 }
  1324.                 else
  1325.                 {
  1326.                         // Is the idle sprite visible on the screen?
  1327.                     if (curSpriteP->destRectIsVisible)
  1328.                     {
  1329.                         SWCheckWrappedIdleSpriteOverlap(spriteWorldP, 
  1330.                             curSpriteP, headActiveSpriteP);
  1331.                     }
  1332.                 }
  1333.             }
  1334.             
  1335.                 // Set last rect to current rect
  1336.             curSpriteP->oldFrameRect = curSpriteP->destFrameRect;
  1337.             curSpriteP->oldRectIsVisible = curSpriteP->destRectIsVisible;
  1338.             
  1339.             curSpriteP->needsToBeDrawn = false;
  1340.             curSpriteP->needsToBeErased = false;
  1341.  
  1342.             curSpriteP = curSpriteP->nextSpriteP;
  1343.         }
  1344.         
  1345.         curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;
  1346.     }
  1347.     
  1348.     spriteWorldP->oldVisScrollRect = spriteWorldP->visScrollRect;
  1349.     
  1350.     
  1351.             // Call the postDrawCallBack
  1352.     if (spriteWorldP->postDrawCallBack != NULL)
  1353.         (*spriteWorldP->postDrawCallBack)(spriteWorldP);
  1354.     
  1355.     
  1356.     //-----------------update the screen--------------------
  1357.     
  1358.         // Set the port to the window
  1359.     SetGWorld(spriteWorldP->windowFrameP->framePort, nil);
  1360.     
  1361.     if (spriteWorldP->usingVBL)
  1362.     {  
  1363.         spriteWorldP->vblTaskRec.hasVBLFired = false;
  1364.         while ( !spriteWorldP->vblTaskRec.hasVBLFired )
  1365.         {}
  1366.     }
  1367.     
  1368.     
  1369.     //
  1370.     ///    --------------BEGIN NEW CODE---------------
  1371.     //
  1372.     
  1373.     
  1374.         // update flagged background rects
  1375.     curRectStructP = spriteWorldP->headUpdateRectP;
  1376.     while ( curRectStructP != NULL )
  1377.     {
  1378.         SWWrapRectToScreen(spriteWorldP, &curRectStructP->updateRect);                        
  1379.         curRectStructP = curRectStructP->nextRectStructP;
  1380.     }
  1381.     
  1382.         // Update on screen the tiles that have changed
  1383.     changedRectP = spriteWorldP->changedTiles;
  1384.     for (index = 0; index < spriteWorldP->numTilesChanged; index++, changedRectP++)
  1385.     {
  1386.         SWWrapRectToScreen(spriteWorldP, changedRectP);
  1387.     }
  1388.  
  1389.     
  1390.         // update the sprites on the screen
  1391.     curSpriteP = headActiveSpriteP;
  1392.     while (curSpriteP != NULL)
  1393.     {    
  1394.         SWWrapRectToScreen(spriteWorldP, &curSpriteP->deltaFrameRect);
  1395.         curSpriteP->deltaFrameRect = curSpriteP->destFrameRect;
  1396.         curSpriteP = curSpriteP->nextActiveSpriteP;
  1397.     }
  1398.  
  1399.     //
  1400.     ///    --------------END NEW CODE---------------
  1401.     //
  1402.     
  1403.     
  1404.             // dispose of flagged background rects
  1405.     nextRectStructP = spriteWorldP->headUpdateRectP;
  1406.     while ( nextRectStructP != NULL )
  1407.     {
  1408.         curRectStructP = nextRectStructP;
  1409.         nextRectStructP = curRectStructP->nextRectStructP;
  1410.         DisposePtr( (Ptr)curRectStructP );
  1411.     }
  1412.     spriteWorldP->headUpdateRectP = NULL;
  1413.     
  1414.     spriteWorldP->numTilesChanged = 0;
  1415.     
  1416.     gSWCurrentSpriteWorld = NULL;
  1417.     
  1418.         // Remove the deadSpriteLayer if we added it earlier.
  1419.     if ( spriteWorldP->deadSpriteLayerP->headSpriteP != NULL )
  1420.     {
  1421.         SWRemoveSpriteLayer(spriteWorldP, spriteWorldP->deadSpriteLayerP);
  1422.     }
  1423. }
  1424.  
  1425.  
  1426. ///--------------------------------------------------------------------------------------
  1427. //    SWUnwrapWorkAreaToBackground - copies the work area to the background while "unwrapping"
  1428. //    it, so the user can do special screen wipes or whatever to update the screen while copying
  1429. //    from the background.
  1430. ///--------------------------------------------------------------------------------------
  1431.  
  1432. SW_FUNC void SWUnwrapWorkAreaToBackground(
  1433.     SpriteWorldPtr spriteWorldP)
  1434. {
  1435.     Rect    destRect;
  1436.     
  1437.     destRect = spriteWorldP->offscreenScrollRect;
  1438.     OffsetRect(&destRect, -destRect.left, -destRect.top);
  1439.     
  1440.     SWWrapWorkAreaToFrame(spriteWorldP, spriteWorldP->backFrameP, &destRect);
  1441. }
  1442.  
  1443. #pragma mark -
  1444. ///--------------------------------------------------------------------------------------
  1445. //    SWDrawWrappedSprite - wraps image in dest area. For drawing sprites, not erasing,
  1446. //    since source rect stays the same.
  1447. ///--------------------------------------------------------------------------------------
  1448.  
  1449. SW_FUNC void SWDrawWrappedSprite(
  1450.     SpritePtr srcSpriteP,
  1451.     FramePtr dstFrameP,
  1452.     Rect* srcRect,
  1453.     Rect* dstRect)
  1454. {
  1455.     Rect        tempDstRect;
  1456.     
  1457.     SW_ASSERT(srcSpriteP->frameDrawProc != NULL );
  1458.     SW_ASSERT(srcSpriteP->curFrameP != NULL );
  1459.     
  1460.         // Draw main image //
  1461.     (*srcSpriteP->frameDrawProc)(srcSpriteP->curFrameP, dstFrameP, srcRect, dstRect);
  1462.     
  1463.     
  1464.         // Wrap to top //
  1465.     if (dstRect->bottom > dstFrameP->frameRect.bottom)
  1466.     {
  1467.         tempDstRect.top = dstRect->top - dstFrameP->frameRect.bottom;
  1468.         tempDstRect.bottom = dstRect->bottom - dstFrameP->frameRect.bottom;
  1469.         tempDstRect.left = dstRect->left;
  1470.         tempDstRect.right = dstRect->right;
  1471.         
  1472.         (*srcSpriteP->frameDrawProc)(srcSpriteP->curFrameP, dstFrameP, 
  1473.             srcRect, &tempDstRect);
  1474.         
  1475.         
  1476.             // Wrap to upper left or right corner //
  1477.         if (dstRect->right > dstFrameP->frameRect.right)
  1478.         {
  1479.             tempDstRect.left -= dstFrameP->frameRect.right;
  1480.             tempDstRect.right -= dstFrameP->frameRect.right;
  1481.             
  1482.             (*srcSpriteP->frameDrawProc)(srcSpriteP->curFrameP, dstFrameP, 
  1483.                 srcRect, &tempDstRect);
  1484.         }
  1485.         else if (dstRect->left < dstFrameP->frameRect.left)
  1486.         {
  1487.             tempDstRect.left += dstFrameP->frameRect.right;
  1488.             tempDstRect.right += dstFrameP->frameRect.right;
  1489.             
  1490.             (*srcSpriteP->frameDrawProc)(srcSpriteP->curFrameP, dstFrameP, 
  1491.                 srcRect, &tempDstRect);
  1492.         }
  1493.     }
  1494.     
  1495.             // Wrap to left or right side //
  1496.     if (dstRect->right > dstFrameP->frameRect.right)
  1497.     {
  1498.         tempDstRect.top = dstRect->top;
  1499.         tempDstRect.bottom = dstRect->bottom;
  1500.         tempDstRect.left = dstRect->left - dstFrameP->frameRect.right;
  1501.         tempDstRect.right = dstRect->right - dstFrameP->frameRect.right;
  1502.         
  1503.         (*srcSpriteP->frameDrawProc)(srcSpriteP->curFrameP, dstFrameP, 
  1504.             srcRect, &tempDstRect);
  1505.     }
  1506.     else if (dstRect->left < dstFrameP->frameRect.left)
  1507.     {
  1508.         tempDstRect.top = dstRect->top;
  1509.         tempDstRect.bottom = dstRect->bottom;
  1510.         tempDstRect.left = dstRect->left + dstFrameP->frameRect.right;
  1511.         tempDstRect.right = dstRect->right + dstFrameP->frameRect.right;
  1512.         
  1513.         (*srcSpriteP->frameDrawProc)(srcSpriteP->curFrameP, dstFrameP, 
  1514.             srcRect, &tempDstRect);
  1515.     }
  1516.     
  1517.     
  1518.             // Wrap to bottom //
  1519.     if (dstRect->top < dstFrameP->frameRect.top)
  1520.     {
  1521.         tempDstRect.top = dstRect->top + dstFrameP->frameRect.bottom;
  1522.         tempDstRect.bottom = dstRect->bottom + dstFrameP->frameRect.bottom;
  1523.         tempDstRect.left = dstRect->left;
  1524.         tempDstRect.right = dstRect->right;
  1525.         
  1526.         (*srcSpriteP->frameDrawProc)(srcSpriteP->curFrameP, dstFrameP, 
  1527.             srcRect, &tempDstRect);
  1528.         
  1529.             // Wrap to lower left or right corner //
  1530.         if (dstRect->right > dstFrameP->frameRect.right)
  1531.         {
  1532.             tempDstRect.left -= dstFrameP->frameRect.right;
  1533.             tempDstRect.right -= dstFrameP->frameRect.right;
  1534.             
  1535.             (*srcSpriteP->frameDrawProc)(srcSpriteP->curFrameP, dstFrameP, 
  1536.                 srcRect, &tempDstRect);
  1537.         }
  1538.         else if (dstRect->left < dstFrameP->frameRect.left)
  1539.         {
  1540.             tempDstRect.left += dstFrameP->frameRect.right;
  1541.             tempDstRect.right += dstFrameP->frameRect.right;
  1542.             
  1543.             (*srcSpriteP->frameDrawProc)(srcSpriteP->curFrameP, dstFrameP, 
  1544.                 srcRect, &tempDstRect);
  1545.         }
  1546.     }
  1547. }
  1548.  
  1549.  
  1550. ///--------------------------------------------------------------------------------------
  1551. //    SWEraseWrappedSprite - erases a wrapped sprite from the work area
  1552. ///--------------------------------------------------------------------------------------
  1553.  
  1554. SW_FUNC void SWEraseWrappedSprite(
  1555.     SpriteWorldPtr spriteWorldP,
  1556.     Rect* dstRect)
  1557. {
  1558.     Rect        tempDstRect;
  1559.     FramePtr    srcFrameP = spriteWorldP->backFrameP;
  1560.     FramePtr    dstFrameP = spriteWorldP->workFrameP;
  1561.     
  1562.     
  1563.         // Draw main image //
  1564.     (*spriteWorldP->offscreenDrawProc)(srcFrameP, dstFrameP, dstRect, dstRect);
  1565.     
  1566.     
  1567.         // Wrap to top //
  1568.     if (dstRect->bottom > dstFrameP->frameRect.bottom)
  1569.     {
  1570.         tempDstRect.top = dstRect->top - dstFrameP->frameRect.bottom;
  1571.         tempDstRect.bottom = dstRect->bottom - dstFrameP->frameRect.bottom;
  1572.         tempDstRect.left = dstRect->left;
  1573.         tempDstRect.right = dstRect->right;
  1574.         
  1575.         (*spriteWorldP->offscreenDrawProc)(srcFrameP, dstFrameP, 
  1576.             &tempDstRect, &tempDstRect);
  1577.         
  1578.             // Wrap to upper left or right corner //
  1579.         if (dstRect->right > dstFrameP->frameRect.right)
  1580.         {
  1581.             tempDstRect.left -= dstFrameP->frameRect.right;
  1582.             tempDstRect.right -= dstFrameP->frameRect.right;
  1583.             
  1584.             (*spriteWorldP->offscreenDrawProc)(srcFrameP, dstFrameP, 
  1585.                 &tempDstRect, &tempDstRect);
  1586.         }
  1587.         else if (dstRect->left < dstFrameP->frameRect.left)
  1588.         {
  1589.             tempDstRect.left += dstFrameP->frameRect.right;
  1590.             tempDstRect.right += dstFrameP->frameRect.right;
  1591.             
  1592.             (*spriteWorldP->offscreenDrawProc)(srcFrameP, dstFrameP, 
  1593.                 &tempDstRect, &tempDstRect);
  1594.         }
  1595.     }
  1596.     
  1597.             // Wrap to left or right side //
  1598.     if (dstRect->right > dstFrameP->frameRect.right)
  1599.     {
  1600.         tempDstRect.top = dstRect->top;
  1601.         tempDstRect.bottom = dstRect->bottom;
  1602.         tempDstRect.left = dstRect->left - dstFrameP->frameRect.right;
  1603.         tempDstRect.right = dstRect->right - dstFrameP->frameRect.right;
  1604.         
  1605.         (*spriteWorldP->offscreenDrawProc)(srcFrameP, dstFrameP, 
  1606.             &tempDstRect, &tempDstRect);
  1607.     }
  1608.     else if (dstRect->left < dstFrameP->frameRect.left)
  1609.     {
  1610.         tempDstRect.top = dstRect->top;
  1611.         tempDstRect.bottom = dstRect->bottom;
  1612.         tempDstRect.left = dstRect->left + dstFrameP->frameRect.right;
  1613.         tempDstRect.right = dstRect->right + dstFrameP->frameRect.right;
  1614.         
  1615.         (*spriteWorldP->offscreenDrawProc)(srcFrameP, dstFrameP, 
  1616.             &tempDstRect, &tempDstRect);
  1617.     }
  1618.     
  1619.     
  1620.             // Wrap to bottom //
  1621.     if (dstRect->top < dstFrameP->frameRect.top)
  1622.     {
  1623.         tempDstRect.top = dstRect->top + dstFrameP->frameRect.bottom;
  1624.         tempDstRect.bottom = dstRect->bottom + dstFrameP->frameRect.bottom;
  1625.         tempDstRect.left = dstRect->left;
  1626.         tempDstRect.right = dstRect->right;
  1627.         
  1628.         (*spriteWorldP->offscreenDrawProc)(srcFrameP, dstFrameP, 
  1629.             &tempDstRect, &tempDstRect);
  1630.         
  1631.             // Wrap to lower left or right corner //
  1632.         if (dstRect->right > dstFrameP->frameRect.right)
  1633.         {
  1634.             tempDstRect.left -= dstFrameP->frameRect.right;
  1635.             tempDstRect.right -= dstFrameP->frameRect.right;
  1636.             
  1637.             (*spriteWorldP->offscreenDrawProc)(srcFrameP, dstFrameP, 
  1638.                 &tempDstRect, &tempDstRect);
  1639.         }
  1640.         else if (dstRect->left < dstFrameP->frameRect.left)
  1641.         {
  1642.             tempDstRect.left += dstFrameP->frameRect.right;
  1643.             tempDstRect.right += dstFrameP->frameRect.right;
  1644.             
  1645.             (*spriteWorldP->offscreenDrawProc)(srcFrameP, dstFrameP, 
  1646.                 &tempDstRect, &tempDstRect);
  1647.         }
  1648.     }
  1649. }
  1650.  
  1651.  
  1652. ///--------------------------------------------------------------------------------------
  1653. //    SWWrapWorkAreaToFrame - copy source rect to dest rect while wrapping soruce. Assumes they
  1654. //    are the same size, and that dstRect will fit within the bounds of the dstFrameP. Used 
  1655. //    for copying the work area to the screen, with the ability of "wrapping" the source
  1656. //    rect around the work area. Also used by SWUnwrapWorkAreaToBackground.
  1657. ///--------------------------------------------------------------------------------------
  1658.  
  1659. SW_FUNC void SWWrapWorkAreaToFrame(
  1660.     SpriteWorldPtr    spriteWorldP,
  1661.     FramePtr dstFrameP,
  1662.     Rect *dstRectP)
  1663. {
  1664.     FramePtr    srcFrameP = spriteWorldP->workFrameP;
  1665.     
  1666.         // We can always add code to clip dstRect later if we want.
  1667.         // Just make sure to clip it before clipping srcRect.
  1668.     Rect    srcRect = spriteWorldP->offscreenScrollRect;
  1669.     Rect    dstRect = *dstRectP;
  1670.     Rect    srcRectA, srcRectB, dstRectA, dstRectB;
  1671.     
  1672.                 // Size of area that was clipped in source rect
  1673.     short    topClip=0, rightClip=0, bottomClip=0, leftClip=0;
  1674.     
  1675.     
  1676.         // Clip the source rect, and save what we clipped for wrapping later //
  1677.     
  1678.         // clip off the top
  1679.     if (srcRect.top < srcFrameP->frameRect.top)
  1680.     {
  1681.         topClip = srcFrameP->frameRect.top - srcRect.top;
  1682.         srcRect.top += topClip;    
  1683.     }
  1684.     
  1685.         // clip off the bottom
  1686.     if (srcRect.bottom > srcFrameP->frameRect.bottom)
  1687.     {
  1688.         bottomClip = srcRect.bottom - srcFrameP->frameRect.bottom;
  1689.         srcRect.bottom -= bottomClip;
  1690.     }
  1691.     
  1692.         // clip off the left
  1693.     if (srcRect.left < srcFrameP->frameRect.left)
  1694.     {
  1695.         leftClip = srcFrameP->frameRect.left - srcRect.left;
  1696.         srcRect.left += leftClip;
  1697.     }
  1698.     
  1699.         // clip off the right
  1700.     if (srcRect.right > srcFrameP->frameRect.right)
  1701.     {
  1702.         rightClip = srcRect.right - srcFrameP->frameRect.right;
  1703.         srcRect.right -= rightClip;
  1704.     }
  1705.     
  1706.     
  1707.                     // Here we do the wrapping and drawing //
  1708.     
  1709.         // Draw top section //
  1710.     
  1711.     if (topClip)
  1712.     {
  1713.                 // Calculate top piece //
  1714.         
  1715.             // Wrap source rect to bottom side
  1716.         srcRectA.right = srcRect.right;                    // Copy clipped source rect
  1717.         srcRectA.left = srcRect.left;
  1718.         srcRectA.bottom = srcFrameP->frameRect.bottom;
  1719.         srcRectA.top = srcFrameP->frameRect.bottom - topClip;
  1720.         
  1721.             // Position dest rect at top side
  1722.         dstRectA.top = dstRect.top;
  1723.         dstRectA.bottom = dstRect.top + topClip;
  1724.         dstRectA.left = dstRect.left + leftClip;
  1725.         dstRectA.right = dstRect.right - rightClip;
  1726.         
  1727.         
  1728.         if (leftClip)    // Calculate top-left piece
  1729.         {
  1730.                 // Wrap source rect to lower-right corner
  1731.             srcRectB.bottom = srcFrameP->frameRect.bottom;
  1732.             srcRectB.right = srcFrameP->frameRect.right;
  1733.             srcRectB.top = srcFrameP->frameRect.bottom - topClip;
  1734.             srcRectB.left = srcFrameP->frameRect.right - leftClip;
  1735.             
  1736.                 // Position dest rect at top-left corner
  1737.             dstRectB.left = dstRect.left;
  1738.             dstRectB.top = dstRect.top;
  1739.             dstRectB.right = dstRect.left + leftClip;
  1740.             dstRectB.bottom = dstRect.top + topClip;
  1741.             
  1742.             if (spriteWorldP->doubleRectDrawProc != NULL)
  1743.             {
  1744.                     // RectB is passed first, since it is to the left of rectA
  1745.                 (*spriteWorldP->doubleRectDrawProc)(srcFrameP, dstFrameP, 
  1746.                     &srcRectB, &dstRectB, &srcRectA, &dstRectA);
  1747.             }
  1748.             else
  1749.             {
  1750.                 (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectB, &dstRectB);
  1751.                 (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectA, &dstRectA);
  1752.             }
  1753.         }
  1754.         else if (rightClip)        // Calculate top-right piece
  1755.         {
  1756.                 // Wrap source rect to lower-left corner
  1757.             srcRectB.bottom = srcFrameP->frameRect.bottom;
  1758.             srcRectB.left = srcFrameP->frameRect.left;
  1759.             srcRectB.right = srcFrameP->frameRect.left + rightClip;
  1760.             srcRectB.top = srcFrameP->frameRect.bottom - topClip;
  1761.             
  1762.                 // Position dest rect at top-right corner
  1763.             dstRectB.top = dstRect.top;
  1764.             dstRectB.right = dstRect.right;
  1765.             dstRectB.bottom = dstRect.top + topClip;
  1766.             dstRectB.left = dstRect.right - rightClip;
  1767.             
  1768.             if (spriteWorldP->doubleRectDrawProc != NULL)
  1769.             {
  1770.                 (*spriteWorldP->doubleRectDrawProc)(srcFrameP, dstFrameP,
  1771.                      &srcRectA, &dstRectA, &srcRectB, &dstRectB);
  1772.             }
  1773.             else
  1774.             {
  1775.                 (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectA, &dstRectA);
  1776.                 (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectB, &dstRectB);
  1777.             }
  1778.         }
  1779.         else
  1780.         {
  1781.                 // Draw just the top rect
  1782.             (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectA, &dstRectA);
  1783.         }
  1784.     }
  1785.     
  1786.     
  1787.             // Draw middle section //
  1788.     
  1789.         // Calculate main middle piece (not wrapped)
  1790.     dstRectA.left = dstRect.left + leftClip;
  1791.     dstRectA.top = dstRect.top + topClip;
  1792.     dstRectA.right = dstRect.right - rightClip;
  1793.     dstRectA.bottom = dstRect.bottom - bottomClip;
  1794.     
  1795.     
  1796.     if (leftClip)    // Draw left piece
  1797.     {
  1798.             // Wrap source rect to right side
  1799.         srcRectB.top = srcRect.top;                // Copy clipped source rect
  1800.         srcRectB.bottom = srcRect.bottom;
  1801.         srcRectB.right = srcFrameP->frameRect.right;
  1802.         srcRectB.left = srcFrameP->frameRect.right - leftClip;
  1803.         
  1804.             // Position dest rect at left side
  1805.         dstRectB.left = dstRect.left;
  1806.         dstRectB.right = dstRect.left + leftClip;
  1807.         dstRectB.top = dstRect.top + topClip;
  1808.         dstRectB.bottom = dstRect.bottom - bottomClip;
  1809.         
  1810.         if (spriteWorldP->doubleRectDrawProc != NULL)
  1811.         {
  1812.                 // RectB is passed first, since it is to the left of rectA
  1813.             (*spriteWorldP->doubleRectDrawProc)(srcFrameP, dstFrameP, 
  1814.                 &srcRectB, &dstRectB, &srcRect, &dstRectA);
  1815.         }
  1816.         else
  1817.         {
  1818.             (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectB, &dstRectB);
  1819.             (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRect, &dstRectA);
  1820.         }
  1821.     }
  1822.     else if (rightClip)        // Draw right piece
  1823.     {
  1824.             // Wrap source rect to left side
  1825.         srcRectB.top = srcRect.top;                // Copy clipped source rect
  1826.         srcRectB.bottom = srcRect.bottom;
  1827.         srcRectB.left = srcFrameP->frameRect.left;
  1828.         srcRectB.right = srcFrameP->frameRect.left + rightClip;
  1829.         
  1830.             // Position dest rect at right side
  1831.         dstRectB.right = dstRect.right;
  1832.         dstRectB.left = dstRect.right - rightClip;
  1833.         dstRectB.top = dstRect.top + topClip;
  1834.         dstRectB.bottom = dstRect.bottom - bottomClip;
  1835.         
  1836.         if (spriteWorldP->doubleRectDrawProc != NULL)
  1837.         {
  1838.             (*spriteWorldP->doubleRectDrawProc)(srcFrameP, dstFrameP, 
  1839.                 &srcRect, &dstRectA, &srcRectB, &dstRectB);
  1840.         }
  1841.         else
  1842.         {
  1843.             (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRect, &dstRectA);
  1844.             (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectB, &dstRectB);
  1845.         }
  1846.     }
  1847.     else
  1848.     {
  1849.             // Draw just the middle piece
  1850.          (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRect, &dstRectA);
  1851.     }
  1852.     
  1853.     
  1854.         // Draw bottom section //
  1855.     
  1856.     if (bottomClip)
  1857.     {
  1858.             // Calculate bottom piece //
  1859.         
  1860.             // Wrap source rect to top side
  1861.         srcRectA.right = srcRect.right;                // Copy clipped source rect
  1862.         srcRectA.left = srcRect.left;
  1863.         srcRectA.top = srcFrameP->frameRect.top;
  1864.         srcRectA.bottom = srcFrameP->frameRect.top + bottomClip;
  1865.         
  1866.             // Position dest rect at bottom side
  1867.         dstRectA.bottom = dstRect.bottom;
  1868.         dstRectA.top = dstRect.bottom - bottomClip;
  1869.         dstRectA.left = dstRect.left + leftClip;
  1870.         dstRectA.right = dstRect.right - rightClip;
  1871.  
  1872.         
  1873.         if (leftClip)     // Draw bottom-left piece
  1874.         {
  1875.                 // Wrap source rect to upper-right corner
  1876.             srcRectB.top = srcFrameP->frameRect.top;
  1877.             srcRectB.right = srcFrameP->frameRect.right;
  1878.             srcRectB.bottom = srcFrameP->frameRect.top + bottomClip;
  1879.             srcRectB.left = srcFrameP->frameRect.right - leftClip;
  1880.             
  1881.                 // Position dest rect at bottom-left corner
  1882.             dstRectB.bottom = dstRect.bottom;
  1883.             dstRectB.left = dstRect.left;
  1884.             dstRectB.top = dstRect.bottom - bottomClip;
  1885.             dstRectB.right = dstRect.left + leftClip;
  1886.             
  1887.             if (spriteWorldP->doubleRectDrawProc != NULL)
  1888.             {
  1889.                     // RectB is passed first, since it is to the left of rectA
  1890.                 (*spriteWorldP->doubleRectDrawProc)(srcFrameP, dstFrameP, 
  1891.                     &srcRectB, &dstRectB, &srcRectA, &dstRectA);
  1892.             }
  1893.             else
  1894.             {
  1895.                 (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectB, &dstRectB);
  1896.                 (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectA, &dstRectA);
  1897.             }
  1898.         }
  1899.         else if (rightClip)        // Draw bottom-right piece
  1900.         {
  1901.                 // Wrap source rect to upper-left corner
  1902.             srcRectB.top = srcFrameP->frameRect.top;
  1903.             srcRectB.left = srcFrameP->frameRect.left;
  1904.             srcRectB.bottom = srcFrameP->frameRect.top + bottomClip;
  1905.             srcRectB.right = srcFrameP->frameRect.left + rightClip;
  1906.             
  1907.                 // Position dest rect at bottom-right corner
  1908.             dstRectB.bottom = dstRect.bottom;
  1909.             dstRectB.right = dstRect.right;
  1910.             dstRectB.top = dstRect.bottom - bottomClip;
  1911.             dstRectB.left = dstRect.right - rightClip;
  1912.             
  1913.             if (spriteWorldP->doubleRectDrawProc != NULL)
  1914.             {
  1915.                 (*spriteWorldP->doubleRectDrawProc)(srcFrameP, dstFrameP, 
  1916.                     &srcRectA, &dstRectA, &srcRectB, &dstRectB);
  1917.             }
  1918.             else
  1919.             {
  1920.                 (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectA, &dstRectA);
  1921.                 (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectB, &dstRectB);
  1922.             }
  1923.         }
  1924.         else
  1925.         {
  1926.                 // Draw just the bottom clip
  1927.             (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectA, &dstRectA);
  1928.         }
  1929.     }
  1930. }
  1931.  
  1932.  
  1933. ///--------------------------------------------------------------------------------------
  1934. //    SWWrapRectToScreen - essentially the same as SWWrapWorkAreaToFrame, except with some
  1935. //    extra code at the beginning to calculate the dstRect based on the srcRect, and clip it.
  1936. //    Used by SWFastAnimateScrollingSpriteWorld.
  1937. ///--------------------------------------------------------------------------------------
  1938.  
  1939. SW_FUNC void SWWrapRectToScreen(
  1940.     SpriteWorldPtr    spriteWorldP,
  1941.     Rect            *srcRectP)
  1942. {    
  1943.     FramePtr    srcFrameP = spriteWorldP->workFrameP;
  1944.     FramePtr    dstFrameP = spriteWorldP->windowFrameP;
  1945.     Rect        srcRect, dstRect, srcRectA, srcRectB, dstRectA, dstRectB;
  1946.     short        topClip=0, rightClip=0, bottomClip=0, leftClip=0;
  1947.     
  1948.     srcRect = *srcRectP;
  1949.     
  1950.         // dstRect = srcRect - spriteWorldP->visScrollRect + spriteWorldP->windRect;
  1951.     dstRect = srcRect;
  1952.     dstRect.top -= spriteWorldP->visScrollRect.top;
  1953.     dstRect.bottom -= spriteWorldP->visScrollRect.top;
  1954.     dstRect.left -= spriteWorldP->visScrollRect.left;
  1955.     dstRect.right -= spriteWorldP->visScrollRect.left;
  1956.     dstRect.top += spriteWorldP->windRect.top;
  1957.     dstRect.bottom += spriteWorldP->windRect.top;
  1958.     dstRect.left += spriteWorldP->windRect.left;
  1959.     dstRect.right += spriteWorldP->windRect.left;
  1960.  
  1961.         // Clip dstRect
  1962.     if (dstRect.top < spriteWorldP->windRect.top)
  1963.     {
  1964.         srcRect.top += spriteWorldP->windRect.top - dstRect.top;
  1965.         dstRect.top = spriteWorldP->windRect.top;
  1966.     }
  1967.     
  1968.     if (dstRect.bottom > spriteWorldP->windRect.bottom)
  1969.     {
  1970.         srcRect.bottom += spriteWorldP->windRect.bottom - dstRect.bottom;
  1971.         dstRect.bottom = spriteWorldP->windRect.bottom;
  1972.     }
  1973.     
  1974.     if (dstRect.left < spriteWorldP->windRect.left)
  1975.     {
  1976.         srcRect.left += spriteWorldP->windRect.left - dstRect.left;
  1977.         dstRect.left = spriteWorldP->windRect.left;
  1978.     }
  1979.     
  1980.     if (dstRect.right > spriteWorldP->windRect.right)
  1981.     {
  1982.         srcRect.right += spriteWorldP->windRect.right - dstRect.right;
  1983.         dstRect.right = spriteWorldP->windRect.right;
  1984.     }
  1985.     
  1986.         // Make sure rect is visible
  1987.     if ( (dstRect.right <= dstRect.left) || (dstRect.bottom <= dstRect.top) )
  1988.         return;
  1989.     
  1990.         // Make the srcRect local to the offscreen area
  1991.     srcRect.top -= spriteWorldP->vertScrollRectOffset;
  1992.     srcRect.bottom -= spriteWorldP->vertScrollRectOffset;
  1993.     srcRect.left -= spriteWorldP->horizScrollRectOffset;
  1994.     srcRect.right -= spriteWorldP->horizScrollRectOffset;
  1995.  
  1996.     
  1997.         // Clip the source rect, and save what we clipped for wrapping later //
  1998.     
  1999.         // clip off the top
  2000.     if (srcRect.top < srcFrameP->frameRect.top)
  2001.     {
  2002.         topClip = srcFrameP->frameRect.top - srcRect.top;
  2003.         srcRect.top += topClip;    
  2004.     }
  2005.     
  2006.         // clip off the bottom
  2007.     if (srcRect.bottom > srcFrameP->frameRect.bottom)
  2008.     {
  2009.         bottomClip = srcRect.bottom - srcFrameP->frameRect.bottom;
  2010.         srcRect.bottom -= bottomClip;
  2011.     }
  2012.     
  2013.         // clip off the left
  2014.     if (srcRect.left < srcFrameP->frameRect.left)
  2015.     {
  2016.         leftClip = srcFrameP->frameRect.left - srcRect.left;
  2017.         srcRect.left += leftClip;
  2018.     }
  2019.     
  2020.         // clip off the right
  2021.     if (srcRect.right > srcFrameP->frameRect.right)
  2022.     {
  2023.         rightClip = srcRect.right - srcFrameP->frameRect.right;
  2024.         srcRect.right -= rightClip;
  2025.     }
  2026.     
  2027.     
  2028.                     // Here we do the wrapping and drawing //
  2029.     
  2030.         // Draw top section //
  2031.     
  2032.     if (topClip)
  2033.     {
  2034.                 // Calculate top piece //
  2035.         
  2036.             // Wrap source rect to bottom side
  2037.         srcRectA.right = srcRect.right;                    // Copy clipped source rect
  2038.         srcRectA.left = srcRect.left;
  2039.         srcRectA.bottom = srcFrameP->frameRect.bottom;
  2040.         srcRectA.top = srcFrameP->frameRect.bottom - topClip;
  2041.         
  2042.             // Position dest rect at top side
  2043.         dstRectA.top = dstRect.top;
  2044.         dstRectA.bottom = dstRect.top + topClip;
  2045.         dstRectA.left = dstRect.left + leftClip;
  2046.         dstRectA.right = dstRect.right - rightClip;
  2047.         
  2048.         
  2049.         if (leftClip)    // Calculate top-left piece
  2050.         {
  2051.                 // Wrap source rect to lower-right corner
  2052.             srcRectB.bottom = srcFrameP->frameRect.bottom;
  2053.             srcRectB.right = srcFrameP->frameRect.right;
  2054.             srcRectB.top = srcFrameP->frameRect.bottom - topClip;
  2055.             srcRectB.left = srcFrameP->frameRect.right - leftClip;
  2056.             
  2057.                 // Position dest rect at top-left corner
  2058.             dstRectB.left = dstRect.left;
  2059.             dstRectB.top = dstRect.top;
  2060.             dstRectB.right = dstRect.left + leftClip;
  2061.             dstRectB.bottom = dstRect.top + topClip;
  2062.             
  2063.             if (spriteWorldP->doubleRectDrawProc != NULL)
  2064.             {
  2065.                     // RectB is passed first, since it is to the left of rectA
  2066.                 (*spriteWorldP->doubleRectDrawProc)(srcFrameP, dstFrameP, 
  2067.                     &srcRectB, &dstRectB, &srcRectA, &dstRectA);
  2068.             }
  2069.             else
  2070.             {
  2071.                 (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectB, &dstRectB);
  2072.                 (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectA, &dstRectA);
  2073.             }
  2074.         }
  2075.         else if (rightClip)        // Calculate top-right piece
  2076.         {
  2077.                 // Wrap source rect to lower-left corner
  2078.             srcRectB.bottom = srcFrameP->frameRect.bottom;
  2079.             srcRectB.left = srcFrameP->frameRect.left;
  2080.             srcRectB.right = srcFrameP->frameRect.left + rightClip;
  2081.             srcRectB.top = srcFrameP->frameRect.bottom - topClip;
  2082.             
  2083.                 // Position dest rect at top-right corner
  2084.             dstRectB.top = dstRect.top;
  2085.             dstRectB.right = dstRect.right;
  2086.             dstRectB.bottom = dstRect.top + topClip;
  2087.             dstRectB.left = dstRect.right - rightClip;
  2088.             
  2089.             if (spriteWorldP->doubleRectDrawProc != NULL)
  2090.             {
  2091.                 (*spriteWorldP->doubleRectDrawProc)(srcFrameP, dstFrameP,
  2092.                      &srcRectA, &dstRectA, &srcRectB, &dstRectB);
  2093.             }
  2094.             else
  2095.             {
  2096.                 (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectA, &dstRectA);
  2097.                 (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectB, &dstRectB);
  2098.             }
  2099.         }
  2100.         else
  2101.         {
  2102.                 // Draw just the top rect
  2103.             (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectA, &dstRectA);
  2104.         }
  2105.     }
  2106.     
  2107.     
  2108.             // Draw middle section //
  2109.     
  2110.         // Calculate main middle piece (not wrapped)
  2111.     dstRectA.left = dstRect.left + leftClip;
  2112.     dstRectA.top = dstRect.top + topClip;
  2113.     dstRectA.right = dstRect.right - rightClip;
  2114.     dstRectA.bottom = dstRect.bottom - bottomClip;
  2115.     
  2116.     
  2117.     if (leftClip)    // Draw left piece
  2118.     {
  2119.             // Wrap source rect to right side
  2120.         srcRectB.top = srcRect.top;                // Copy clipped source rect
  2121.         srcRectB.bottom = srcRect.bottom;
  2122.         srcRectB.right = srcFrameP->frameRect.right;
  2123.         srcRectB.left = srcFrameP->frameRect.right - leftClip;
  2124.         
  2125.             // Position dest rect at left side
  2126.         dstRectB.left = dstRect.left;
  2127.         dstRectB.right = dstRect.left + leftClip;
  2128.         dstRectB.top = dstRect.top + topClip;
  2129.         dstRectB.bottom = dstRect.bottom - bottomClip;
  2130.         
  2131.         if (spriteWorldP->doubleRectDrawProc != NULL)
  2132.         {
  2133.                 // RectB is passed first, since it is to the left of rectA
  2134.             (*spriteWorldP->doubleRectDrawProc)(srcFrameP, dstFrameP, 
  2135.                 &srcRectB, &dstRectB, &srcRect, &dstRectA);
  2136.         }
  2137.         else
  2138.         {
  2139.             (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectB, &dstRectB);
  2140.             (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRect, &dstRectA);
  2141.         }
  2142.     }
  2143.     else if (rightClip)        // Draw right piece
  2144.     {
  2145.             // Wrap source rect to left side
  2146.         srcRectB.top = srcRect.top;                // Copy clipped source rect
  2147.         srcRectB.bottom = srcRect.bottom;
  2148.         srcRectB.left = srcFrameP->frameRect.left;
  2149.         srcRectB.right = srcFrameP->frameRect.left + rightClip;
  2150.         
  2151.             // Position dest rect at right side
  2152.         dstRectB.right = dstRect.right;
  2153.         dstRectB.left = dstRect.right - rightClip;
  2154.         dstRectB.top = dstRect.top + topClip;
  2155.         dstRectB.bottom = dstRect.bottom - bottomClip;
  2156.         
  2157.         if (spriteWorldP->doubleRectDrawProc != NULL)
  2158.         {
  2159.             (*spriteWorldP->doubleRectDrawProc)(srcFrameP, dstFrameP, 
  2160.                 &srcRect, &dstRectA, &srcRectB, &dstRectB);
  2161.         }
  2162.         else
  2163.         {
  2164.             (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRect, &dstRectA);
  2165.             (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectB, &dstRectB);
  2166.         }
  2167.     }
  2168.     else
  2169.     {
  2170.             // Draw just the middle piece
  2171.          (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRect, &dstRectA);
  2172.     }
  2173.     
  2174.     
  2175.         // Draw bottom section //
  2176.     
  2177.     if (bottomClip)
  2178.     {
  2179.             // Calculate bottom piece //
  2180.         
  2181.             // Wrap source rect to top side
  2182.         srcRectA.right = srcRect.right;                // Copy clipped source rect
  2183.         srcRectA.left = srcRect.left;
  2184.         srcRectA.top = srcFrameP->frameRect.top;
  2185.         srcRectA.bottom = srcFrameP->frameRect.top + bottomClip;
  2186.         
  2187.             // Position dest rect at bottom side
  2188.         dstRectA.bottom = dstRect.bottom;
  2189.         dstRectA.top = dstRect.bottom - bottomClip;
  2190.         dstRectA.left = dstRect.left + leftClip;
  2191.         dstRectA.right = dstRect.right - rightClip;
  2192.  
  2193.         
  2194.         if (leftClip)     // Draw bottom-left piece
  2195.         {
  2196.                 // Wrap source rect to upper-right corner
  2197.             srcRectB.top = srcFrameP->frameRect.top;
  2198.             srcRectB.right = srcFrameP->frameRect.right;
  2199.             srcRectB.bottom = srcFrameP->frameRect.top + bottomClip;
  2200.             srcRectB.left = srcFrameP->frameRect.right - leftClip;
  2201.             
  2202.                 // Position dest rect at bottom-left corner
  2203.             dstRectB.bottom = dstRect.bottom;
  2204.             dstRectB.left = dstRect.left;
  2205.             dstRectB.top = dstRect.bottom - bottomClip;
  2206.             dstRectB.right = dstRect.left + leftClip;
  2207.             
  2208.             if (spriteWorldP->doubleRectDrawProc != NULL)
  2209.             {
  2210.                     // RectB is passed first, since it is to the left of rectA
  2211.                 (*spriteWorldP->doubleRectDrawProc)(srcFrameP, dstFrameP, 
  2212.                     &srcRectB, &dstRectB, &srcRectA, &dstRectA);
  2213.             }
  2214.             else
  2215.             {
  2216.                 (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectB, &dstRectB);
  2217.                 (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectA, &dstRectA);
  2218.             }
  2219.         }
  2220.         else if (rightClip)        // Draw bottom-right piece
  2221.         {
  2222.                 // Wrap source rect to upper-left corner
  2223.             srcRectB.top = srcFrameP->frameRect.top;
  2224.             srcRectB.left = srcFrameP->frameRect.left;
  2225.             srcRectB.bottom = srcFrameP->frameRect.top + bottomClip;
  2226.             srcRectB.right = srcFrameP->frameRect.left + rightClip;
  2227.             
  2228.                 // Position dest rect at bottom-right corner
  2229.             dstRectB.bottom = dstRect.bottom;
  2230.             dstRectB.right = dstRect.right;
  2231.             dstRectB.top = dstRect.bottom - bottomClip;
  2232.             dstRectB.left = dstRect.right - rightClip;
  2233.             
  2234.             if (spriteWorldP->doubleRectDrawProc != NULL)
  2235.             {
  2236.                 (*spriteWorldP->doubleRectDrawProc)(srcFrameP, dstFrameP, 
  2237.                     &srcRectA, &dstRectA, &srcRectB, &dstRectB);
  2238.             }
  2239.             else
  2240.             {
  2241.                 (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectA, &dstRectA);
  2242.                 (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectB, &dstRectB);
  2243.             }
  2244.         }
  2245.         else
  2246.         {
  2247.                 // Draw just the bottom clip
  2248.             (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectA, &dstRectA);
  2249.         }
  2250.     }
  2251. }
  2252.  
  2253.  
  2254.  
  2255. ///--------------------------------------------------------------------------------------
  2256. //    SWCheckWrappedIdleSpriteOverlap - same as SWCheckIdleSpriteOverlap, 
  2257. //    but for scrolling SpriteWorlds.
  2258. ///--------------------------------------------------------------------------------------
  2259.  
  2260. SW_FUNC void SWCheckWrappedIdleSpriteOverlap(
  2261.     SpriteWorldPtr    spriteWorldP,
  2262.     SpritePtr        idleSpriteP,
  2263.     SpritePtr        headActiveSpriteP)
  2264. {
  2265.     Rect                *visScrollRectP = &spriteWorldP->visScrollRect;
  2266.     register SpritePtr    activeSpriteP = headActiveSpriteP;
  2267.     Rect                srcSectRect,
  2268.                         dstSectRect;
  2269.     
  2270.     
  2271.         // iterate through the active sprites
  2272.     while (activeSpriteP != NULL)
  2273.     {        
  2274.             // do the sprites overlap?
  2275.         if ((idleSpriteP->oldFrameRect.top < activeSpriteP->deltaFrameRect.bottom) &&
  2276.              (idleSpriteP->oldFrameRect.bottom > activeSpriteP->deltaFrameRect.top) &&
  2277.              (idleSpriteP->oldFrameRect.left < activeSpriteP->deltaFrameRect.right) &&
  2278.              (idleSpriteP->oldFrameRect.right > activeSpriteP->deltaFrameRect.left))
  2279.         {
  2280.                 // calculate the intersection between the idle sprite's destination
  2281.                 // rect, and the active sprite's delta rect
  2282.             dstSectRect.left = 
  2283.                 SW_MAX(idleSpriteP->destFrameRect.left, activeSpriteP->deltaFrameRect.left);
  2284.             dstSectRect.top = 
  2285.                 SW_MAX(idleSpriteP->destFrameRect.top, activeSpriteP->deltaFrameRect.top);
  2286.             dstSectRect.right = 
  2287.                 SW_MIN(idleSpriteP->destFrameRect.right, activeSpriteP->deltaFrameRect.right);
  2288.             dstSectRect.bottom = 
  2289.                 SW_MIN(idleSpriteP->destFrameRect.bottom, activeSpriteP->deltaFrameRect.bottom);
  2290.             
  2291.                 // Clip the sprite's dstSectRect with visScrollRect
  2292.             if (dstSectRect.top < visScrollRectP->top)
  2293.                 dstSectRect.top = visScrollRectP->top;
  2294.             if (dstSectRect.bottom > visScrollRectP->bottom)
  2295.                 dstSectRect.bottom = visScrollRectP->bottom;
  2296.             if (dstSectRect.left < visScrollRectP->left)
  2297.                 dstSectRect.left = visScrollRectP->left;
  2298.             if (dstSectRect.right > visScrollRectP->right)
  2299.                 dstSectRect.right = visScrollRectP->right;
  2300.             
  2301.                 // Calculate the source rect
  2302.             srcSectRect = idleSpriteP->curFrameP->frameRect;
  2303.             
  2304.             srcSectRect.left += (dstSectRect.left - idleSpriteP->destFrameRect.left);
  2305.             srcSectRect.top += (dstSectRect.top - idleSpriteP->destFrameRect.top);
  2306.             srcSectRect.right -= (idleSpriteP->destFrameRect.right - dstSectRect.right);
  2307.             srcSectRect.bottom -= (idleSpriteP->destFrameRect.bottom - dstSectRect.bottom);
  2308.             
  2309.             
  2310.                 // Make the sprite's dest rect local to the offscreen area
  2311.             dstSectRect.top -= spriteWorldP->vertScrollRectOffset;
  2312.             dstSectRect.bottom -= spriteWorldP->vertScrollRectOffset;
  2313.             dstSectRect.left -= spriteWorldP->horizScrollRectOffset;
  2314.             dstSectRect.right -= spriteWorldP->horizScrollRectOffset;
  2315.         
  2316.             gSWCurrentSpriteBeingDrawn = idleSpriteP;
  2317.  
  2318.                 // Copy a piece of the sprite image onto the back drop piece    
  2319.             SWDrawWrappedSprite(idleSpriteP, spriteWorldP->workFrameP,
  2320.                 &srcSectRect, &dstSectRect);
  2321.             
  2322.             gSWCurrentSpriteBeingDrawn = NULL;
  2323.             
  2324.             if (spriteWorldP->tilingIsOn &&
  2325.                 idleSpriteP->tileDepth <= spriteWorldP->lastActiveTileLayer)
  2326.             {
  2327.                 dstSectRect.top += spriteWorldP->vertScrollRectOffset;
  2328.                 dstSectRect.bottom += spriteWorldP->vertScrollRectOffset;
  2329.                 dstSectRect.left += spriteWorldP->horizScrollRectOffset;
  2330.                 dstSectRect.right += spriteWorldP->horizScrollRectOffset;
  2331.                 SWDrawTilesAboveSprite(spriteWorldP, &dstSectRect, idleSpriteP->tileDepth);
  2332.             }
  2333.         }
  2334.         
  2335.         activeSpriteP = activeSpriteP->nextActiveSpriteP;
  2336.     }
  2337. }
  2338.  
  2339.  
  2340. ///--------------------------------------------------------------------------------------
  2341. //    SWCheckWrappedIdleSpritesWithTiles - redraw sprites erased by tiles that changed
  2342. ///--------------------------------------------------------------------------------------
  2343.  
  2344. SW_FUNC void SWCheckWrappedIdleSpritesWithTiles(
  2345.     SpriteWorldPtr    spriteWorldP,
  2346.     SpritePtr        headIdleSpriteP)
  2347. {
  2348.     Rect        *visScrollRectP = &spriteWorldP->visScrollRect;
  2349.     Rect        srcSectRect, dstSectRect;
  2350.     register    SpritePtr idleSpriteP;
  2351.     Rect        *changedRectP;
  2352.     short        index;
  2353.     
  2354.  
  2355.         // Cycle through the changedTiles array of rects
  2356.     changedRectP = spriteWorldP->changedTiles;
  2357.     for (index = 0; index < spriteWorldP->numTilesChanged; index++, changedRectP++)
  2358.     {
  2359.         idleSpriteP = headIdleSpriteP;
  2360.     
  2361.             // iterate through the idle sprites
  2362.         while (idleSpriteP != NULL)
  2363.         {
  2364.                 // does the idle sprite overlap the changedRect?
  2365.             if ((idleSpriteP->oldFrameRect.top < changedRectP->bottom) &&
  2366.                  (idleSpriteP->oldFrameRect.bottom > changedRectP->top) &&
  2367.                  (idleSpriteP->oldFrameRect.left < changedRectP->right) &&
  2368.                  (idleSpriteP->oldFrameRect.right > changedRectP->left))
  2369.             {
  2370.                     // calculate the intersection between the idle sprite's old
  2371.                     // rect and the changedRectP
  2372.                 dstSectRect.left = SW_MAX(idleSpriteP->oldFrameRect.left, 
  2373.                                         changedRectP->left);
  2374.                 dstSectRect.top = SW_MAX(idleSpriteP->oldFrameRect.top, 
  2375.                                         changedRectP->top);
  2376.                 dstSectRect.right = SW_MIN(idleSpriteP->oldFrameRect.right, 
  2377.                                         changedRectP->right);
  2378.                 dstSectRect.bottom = SW_MIN(idleSpriteP->oldFrameRect.bottom, 
  2379.                                         changedRectP->bottom);
  2380.                 
  2381.                     // Clip the sprite's dstSectRect with visScrollRect
  2382.                 if (dstSectRect.top < visScrollRectP->top)
  2383.                     dstSectRect.top = visScrollRectP->top;
  2384.                 if (dstSectRect.bottom > visScrollRectP->bottom)
  2385.                     dstSectRect.bottom = visScrollRectP->bottom;
  2386.                 if (dstSectRect.left < visScrollRectP->left)
  2387.                     dstSectRect.left = visScrollRectP->left;
  2388.                 if (dstSectRect.right > visScrollRectP->right)
  2389.                     dstSectRect.right = visScrollRectP->right;
  2390.                     
  2391.                     // Calculate the source rect
  2392.                 srcSectRect = idleSpriteP->curFrameP->frameRect;
  2393.                 
  2394.                 srcSectRect.left += (dstSectRect.left - idleSpriteP->oldFrameRect.left);
  2395.                 srcSectRect.top += (dstSectRect.top - idleSpriteP->oldFrameRect.top);
  2396.                 srcSectRect.right -= (idleSpriteP->oldFrameRect.right - dstSectRect.right);
  2397.                 srcSectRect.bottom -= (idleSpriteP->oldFrameRect.bottom - dstSectRect.bottom);
  2398.                 
  2399.                 
  2400.                     // Make the sprite's dest rect local to the offscreen area
  2401.                 dstSectRect.top -= spriteWorldP->vertScrollRectOffset;
  2402.                 dstSectRect.bottom -= spriteWorldP->vertScrollRectOffset;
  2403.                 dstSectRect.left -= spriteWorldP->horizScrollRectOffset;
  2404.                 dstSectRect.right -= spriteWorldP->horizScrollRectOffset;
  2405.     
  2406.                 gSWCurrentSpriteBeingDrawn = idleSpriteP;
  2407.     
  2408.                     // Copy a piece of the sprite image onto the back drop piece    
  2409.                 SWDrawWrappedSprite(idleSpriteP, spriteWorldP->workFrameP,
  2410.                     &srcSectRect, &dstSectRect);
  2411.                     
  2412.                 gSWCurrentSpriteBeingDrawn = NULL;
  2413.                 
  2414.                 if (spriteWorldP->tilingIsOn &&
  2415.                     idleSpriteP->tileDepth <= spriteWorldP->lastActiveTileLayer)
  2416.                 {
  2417.                     dstSectRect.top += spriteWorldP->vertScrollRectOffset;
  2418.                     dstSectRect.bottom += spriteWorldP->vertScrollRectOffset;
  2419.                     dstSectRect.left += spriteWorldP->horizScrollRectOffset;
  2420.                     dstSectRect.right += spriteWorldP->horizScrollRectOffset;
  2421.                     SWDrawTilesAboveSprite(spriteWorldP, &dstSectRect, idleSpriteP->tileDepth);
  2422.                 }
  2423.             }
  2424.             
  2425.             idleSpriteP = idleSpriteP->nextIdleSpriteP;
  2426.         }
  2427.     }
  2428. }
  2429.  
  2430.  
  2431. ///--------------------------------------------------------------------------------------
  2432. //    SWCheckWrappedIdleSpritesWithRects - redraw sprites erased by updateRects
  2433. ///--------------------------------------------------------------------------------------
  2434.  
  2435. SW_FUNC void SWCheckWrappedIdleSpritesWithRects(
  2436.     SpriteWorldPtr    spriteWorldP,
  2437.     SpritePtr        headIdleSpriteP)
  2438. {
  2439.     UpdateRectStructPtr    curRectStructP;
  2440.     register SpritePtr    idleSpriteP;
  2441.     Rect                *visScrollRectP = &spriteWorldP->visScrollRect;
  2442.     Rect                srcSectRect, dstSectRect;
  2443.     Rect                *changedRectP;
  2444.     
  2445.     
  2446.     curRectStructP = spriteWorldP->headUpdateRectP;
  2447.     
  2448.     while (curRectStructP != NULL)
  2449.     {
  2450.         changedRectP = &curRectStructP->updateRect;
  2451.         idleSpriteP = headIdleSpriteP;
  2452.     
  2453.             // iterate through the idle sprites
  2454.         while (idleSpriteP != NULL)
  2455.         {
  2456.                 // does the idle sprite overlap the changedRect?
  2457.             if ((idleSpriteP->oldFrameRect.top < changedRectP->bottom) &&
  2458.                  (idleSpriteP->oldFrameRect.bottom > changedRectP->top) &&
  2459.                  (idleSpriteP->oldFrameRect.left < changedRectP->right) &&
  2460.                  (idleSpriteP->oldFrameRect.right > changedRectP->left))
  2461.             {
  2462.                     // calculate the intersection between the idle sprite's old
  2463.                     // rect and the changedRectP
  2464.                 dstSectRect.left = SW_MAX(idleSpriteP->oldFrameRect.left, 
  2465.                                         changedRectP->left);
  2466.                 dstSectRect.top = SW_MAX(idleSpriteP->oldFrameRect.top, 
  2467.                                         changedRectP->top);
  2468.                 dstSectRect.right = SW_MIN(idleSpriteP->oldFrameRect.right, 
  2469.                                         changedRectP->right);
  2470.                 dstSectRect.bottom = SW_MIN(idleSpriteP->oldFrameRect.bottom, 
  2471.                                         changedRectP->bottom);
  2472.                 
  2473.                     // Clip the sprite's dstSectRect with visScrollRect
  2474.                 if (dstSectRect.top < visScrollRectP->top)
  2475.                     dstSectRect.top = visScrollRectP->top;
  2476.                 if (dstSectRect.bottom > visScrollRectP->bottom)
  2477.                     dstSectRect.bottom = visScrollRectP->bottom;
  2478.                 if (dstSectRect.left < visScrollRectP->left)
  2479.                     dstSectRect.left = visScrollRectP->left;
  2480.                 if (dstSectRect.right > visScrollRectP->right)
  2481.                     dstSectRect.right = visScrollRectP->right;
  2482.                     
  2483.                     // Calculate the source rect
  2484.                 srcSectRect = idleSpriteP->curFrameP->frameRect;
  2485.                 
  2486.                 srcSectRect.left += (dstSectRect.left - idleSpriteP->oldFrameRect.left);
  2487.                 srcSectRect.top += (dstSectRect.top - idleSpriteP->oldFrameRect.top);
  2488.                 srcSectRect.right -= (idleSpriteP->oldFrameRect.right - dstSectRect.right);
  2489.                 srcSectRect.bottom -= (idleSpriteP->oldFrameRect.bottom - dstSectRect.bottom);
  2490.                 
  2491.                 
  2492.                     // Make the sprite's dest rect local to the offscreen area
  2493.                 dstSectRect.top -= spriteWorldP->vertScrollRectOffset;
  2494.                 dstSectRect.bottom -= spriteWorldP->vertScrollRectOffset;
  2495.                 dstSectRect.left -= spriteWorldP->horizScrollRectOffset;
  2496.                 dstSectRect.right -= spriteWorldP->horizScrollRectOffset;
  2497.                 
  2498.                 gSWCurrentSpriteBeingDrawn = idleSpriteP;
  2499.     
  2500.                     // Copy a piece of the sprite image onto the back drop piece    
  2501.                 SWDrawWrappedSprite(idleSpriteP, spriteWorldP->workFrameP,
  2502.                     &srcSectRect, &dstSectRect);
  2503.                     
  2504.                 gSWCurrentSpriteBeingDrawn = NULL;
  2505.                 
  2506.                 if (spriteWorldP->tilingIsOn &&
  2507.                     idleSpriteP->tileDepth <= spriteWorldP->lastActiveTileLayer)
  2508.                 {
  2509.                     dstSectRect.top += spriteWorldP->vertScrollRectOffset;
  2510.                     dstSectRect.bottom += spriteWorldP->vertScrollRectOffset;
  2511.                     dstSectRect.left += spriteWorldP->horizScrollRectOffset;
  2512.                     dstSectRect.right += spriteWorldP->horizScrollRectOffset;
  2513.                     SWDrawTilesAboveSprite(spriteWorldP, &dstSectRect, idleSpriteP->tileDepth);
  2514.                 }
  2515.             }
  2516.  
  2517.             idleSpriteP = idleSpriteP->nextIdleSpriteP;
  2518.         }
  2519.         
  2520.         curRectStructP = curRectStructP->nextRectStructP;
  2521.     }
  2522. }
  2523.  
  2524.  
  2525. #pragma mark -
  2526. ///--------------------------------------------------------------------------------------
  2527. //  SWSetScrollingWorldMoveBounds
  2528. ///--------------------------------------------------------------------------------------
  2529.  
  2530. SW_FUNC void SWSetScrollingWorldMoveBounds(
  2531.     SpriteWorldPtr    spriteWorldP,
  2532.     Rect* scrollRectMoveBounds)
  2533. {
  2534.     spriteWorldP->scrollRectMoveBounds = *scrollRectMoveBounds;
  2535.     
  2536.         // Make sure the visScrollRect is still within its bounds
  2537.     SWMoveVisScrollRect(spriteWorldP, 
  2538.             spriteWorldP->visScrollRect.left,
  2539.             spriteWorldP->visScrollRect.top);
  2540. }
  2541.  
  2542.  
  2543. ///--------------------------------------------------------------------------------------
  2544. //    SWSetScrollingWorldMoveProc
  2545. ///--------------------------------------------------------------------------------------
  2546.  
  2547. SW_FUNC void SWSetScrollingWorldMoveProc(
  2548.     SpriteWorldPtr spriteWorldP, 
  2549.     WorldMoveProcPtr worldMoveProcP, 
  2550.     SpritePtr followSpriteP)
  2551. {
  2552.     spriteWorldP->worldMoveProc = worldMoveProcP;
  2553.     spriteWorldP->followSpriteP = followSpriteP;
  2554. }
  2555.  
  2556.  
  2557. ///--------------------------------------------------------------------------------------
  2558. //    SWSetDoubleRectDrawProc
  2559. ///--------------------------------------------------------------------------------------
  2560.  
  2561. SW_FUNC void SWSetDoubleRectDrawProc(
  2562.     SpriteWorldPtr        spriteWorldP,
  2563.     DoubleDrawProcPtr    drawProc)
  2564. {
  2565.     spriteWorldP->doubleRectDrawProc = drawProc;
  2566. }
  2567.  
  2568.  
  2569. ///--------------------------------------------------------------------------------------
  2570. //  SWSetSpriteWorldScrollDelta
  2571. ///--------------------------------------------------------------------------------------
  2572.  
  2573. SW_FUNC void SWSetSpriteWorldScrollDelta(
  2574.     SpriteWorldPtr    spriteWorldP,
  2575.     short            horizDelta,
  2576.     short            vertDelta)
  2577. {
  2578.     spriteWorldP->horizScrollDelta = horizDelta;
  2579.     spriteWorldP->vertScrollDelta = vertDelta;
  2580. }
  2581.  
  2582.  
  2583. ///--------------------------------------------------------------------------------------
  2584. //  SWMoveVisScrollRect - move visScrollRect to an absolute vertical and 
  2585. //    horizontal location
  2586. ///--------------------------------------------------------------------------------------
  2587.  
  2588. SW_FUNC void SWMoveVisScrollRect(
  2589.     SpriteWorldPtr    spriteWorldP,
  2590.     short            horizPos,
  2591.     short            vertPos)
  2592. {
  2593.     short    width, height;
  2594.     
  2595.     height = spriteWorldP->visScrollRect.bottom - spriteWorldP->visScrollRect.top;
  2596.     width = spriteWorldP->visScrollRect.right - spriteWorldP->visScrollRect.left;
  2597.     
  2598.     
  2599.             // Move visScrollRect and keep within moveBounds //
  2600.  
  2601.     
  2602.         // Move vertically
  2603.     if ((long)vertPos < spriteWorldP->scrollRectMoveBounds.top)
  2604.     {
  2605.         spriteWorldP->visScrollRect.top = spriteWorldP->scrollRectMoveBounds.top;
  2606.         spriteWorldP->visScrollRect.bottom = spriteWorldP->visScrollRect.top + height;
  2607.     }
  2608.     else if ((long)vertPos + height > spriteWorldP->scrollRectMoveBounds.bottom)
  2609.     {
  2610.         spriteWorldP->visScrollRect.bottom = spriteWorldP->scrollRectMoveBounds.bottom;
  2611.         spriteWorldP->visScrollRect.top = spriteWorldP->visScrollRect.bottom - height;
  2612.     }
  2613.     else
  2614.     {
  2615.         spriteWorldP->visScrollRect.top = vertPos;
  2616.         spriteWorldP->visScrollRect.bottom = vertPos + height;
  2617.     }
  2618.     
  2619.     
  2620.         // Move horizontally
  2621.     if ((long)horizPos < spriteWorldP->scrollRectMoveBounds.left)
  2622.     {
  2623.         spriteWorldP->visScrollRect.left = spriteWorldP->scrollRectMoveBounds.left;
  2624.         spriteWorldP->visScrollRect.right = spriteWorldP->visScrollRect.left + width;
  2625.     }
  2626.     else if ((long)horizPos + width > spriteWorldP->scrollRectMoveBounds.right)
  2627.     {
  2628.         spriteWorldP->visScrollRect.right = spriteWorldP->scrollRectMoveBounds.right;
  2629.         spriteWorldP->visScrollRect.left = spriteWorldP->visScrollRect.right - width;
  2630.     }
  2631.     else
  2632.     {
  2633.         spriteWorldP->visScrollRect.left = horizPos;
  2634.         spriteWorldP->visScrollRect.right = horizPos + width;
  2635.     }
  2636.     
  2637.     
  2638.     SWCalculateOffscreenScrollRect(spriteWorldP);
  2639. }
  2640.  
  2641.  
  2642. ///--------------------------------------------------------------------------------------
  2643. //  SWOffsetVisScrollRect - move visScrollRect to an absolute vertical and 
  2644. //    horizontal location, while keeping within the bounds of scrollRectMoveBounds
  2645. ///--------------------------------------------------------------------------------------
  2646.  
  2647. SW_FUNC void SWOffsetVisScrollRect(
  2648.     SpriteWorldPtr    spriteWorldP,
  2649.     short            horizOffset,
  2650.     short            vertOffset)
  2651. {
  2652.             // Move visScrollRect and keep within moveBounds //
  2653.  
  2654.         // Move vertically
  2655.     if ((long)spriteWorldP->visScrollRect.top + vertOffset <
  2656.             spriteWorldP->scrollRectMoveBounds.top)
  2657.     {
  2658.         spriteWorldP->visScrollRect.bottom -= spriteWorldP->visScrollRect.top -
  2659.             spriteWorldP->scrollRectMoveBounds.top;
  2660.         spriteWorldP->visScrollRect.top = spriteWorldP->scrollRectMoveBounds.top;
  2661.     }
  2662.     else if ((long)spriteWorldP->visScrollRect.bottom + vertOffset >
  2663.             spriteWorldP->scrollRectMoveBounds.bottom)
  2664.     {
  2665.         spriteWorldP->visScrollRect.top -= spriteWorldP->visScrollRect.bottom -
  2666.             spriteWorldP->scrollRectMoveBounds.bottom;
  2667.         spriteWorldP->visScrollRect.bottom = spriteWorldP->scrollRectMoveBounds.bottom;
  2668.     }
  2669.     else
  2670.     {
  2671.         spriteWorldP->visScrollRect.top += vertOffset;
  2672.         spriteWorldP->visScrollRect.bottom += vertOffset;
  2673.     }
  2674.     
  2675.     
  2676.         // Move horizontally
  2677.     if ((long)spriteWorldP->visScrollRect.left + horizOffset <
  2678.             spriteWorldP->scrollRectMoveBounds.left)
  2679.     {
  2680.         spriteWorldP->visScrollRect.right -= spriteWorldP->visScrollRect.left -
  2681.             spriteWorldP->scrollRectMoveBounds.left;
  2682.         spriteWorldP->visScrollRect.left = spriteWorldP->scrollRectMoveBounds.left;
  2683.     }
  2684.     else if ((long)spriteWorldP->visScrollRect.right + horizOffset >
  2685.             spriteWorldP->scrollRectMoveBounds.right)
  2686.     {
  2687.         spriteWorldP->visScrollRect.left -= spriteWorldP->visScrollRect.right -
  2688.             spriteWorldP->scrollRectMoveBounds.right;
  2689.         spriteWorldP->visScrollRect.right = spriteWorldP->scrollRectMoveBounds.right;
  2690.     }
  2691.     else
  2692.     {
  2693.         spriteWorldP->visScrollRect.left += horizOffset;
  2694.         spriteWorldP->visScrollRect.right += horizOffset;
  2695.     }
  2696.     
  2697.     
  2698.     SWCalculateOffscreenScrollRect(spriteWorldP);
  2699. }
  2700.  
  2701.  
  2702. ///--------------------------------------------------------------------------------------
  2703. //  SWResizeVisScrollRect - make the visScrollRect a new width and height.
  2704. //    Used by SWChangeWorldRect. Make sure to call SWUpdateScrollingSpriteWorld after
  2705. //    calling this.
  2706. ///--------------------------------------------------------------------------------------
  2707.  
  2708. SW_FUNC void SWResizeVisScrollRect(
  2709.     SpriteWorldPtr    spriteWorldP,
  2710.     short            width,
  2711.     short            height)
  2712. {
  2713.         // Will expanding it vertically move it past its bounds?
  2714.     if ((long)spriteWorldP->visScrollRect.top + height > 
  2715.         spriteWorldP->scrollRectMoveBounds.bottom)
  2716.     {
  2717.         spriteWorldP->visScrollRect.bottom = spriteWorldP->scrollRectMoveBounds.bottom;
  2718.         spriteWorldP->visScrollRect.top = spriteWorldP->visScrollRect.bottom - height;
  2719.     }
  2720.     else
  2721.     {
  2722.         spriteWorldP->visScrollRect.bottom = spriteWorldP->visScrollRect.top + height;
  2723.     }
  2724.     
  2725.     
  2726.         // Will expanding it horizontally move it past its bounds?
  2727.     if ((long)spriteWorldP->visScrollRect.left + width > 
  2728.         spriteWorldP->scrollRectMoveBounds.right)
  2729.     {
  2730.         spriteWorldP->visScrollRect.right = spriteWorldP->scrollRectMoveBounds.right;
  2731.         spriteWorldP->visScrollRect.left = spriteWorldP->visScrollRect.right - width;
  2732.     }
  2733.     else
  2734.     {
  2735.         spriteWorldP->visScrollRect.right = spriteWorldP->visScrollRect.left + width;
  2736.     }
  2737.     
  2738.     spriteWorldP->oldVisScrollRect = spriteWorldP->visScrollRect;
  2739.     SWCalculateOffscreenScrollRect(spriteWorldP);
  2740. }
  2741.  
  2742.  
  2743. ///--------------------------------------------------------------------------------------
  2744. //  SWCalculateOffscreenScrollRect (wrap offscreenScrollRect in the work area)
  2745. ///--------------------------------------------------------------------------------------
  2746.  
  2747. SW_FUNC void SWCalculateOffscreenScrollRect(
  2748.     SpriteWorldPtr spriteWorldP)
  2749. {
  2750.     Rect *offscreenScrollRectP = &spriteWorldP->offscreenScrollRect;
  2751.     Rect *visScrollRectP = &spriteWorldP->visScrollRect;
  2752.     
  2753.     
  2754.     spriteWorldP->vertScrollRectOffset = spriteWorldP->backRect.bottom * 
  2755.         (visScrollRectP->top / spriteWorldP->backRect.bottom);
  2756.     
  2757.     spriteWorldP->horizScrollRectOffset = spriteWorldP->backRect.right *
  2758.         (visScrollRectP->left / spriteWorldP->backRect.right);
  2759.     
  2760.     
  2761.     offscreenScrollRectP->top = visScrollRectP->top - 
  2762.             spriteWorldP->vertScrollRectOffset;
  2763.     offscreenScrollRectP->bottom = visScrollRectP->bottom - 
  2764.             spriteWorldP->vertScrollRectOffset;
  2765.     offscreenScrollRectP->left = visScrollRectP->left - 
  2766.             spriteWorldP->horizScrollRectOffset;
  2767.     offscreenScrollRectP->right = visScrollRectP->right - 
  2768.             spriteWorldP->horizScrollRectOffset;
  2769. }
  2770.  
  2771.  
  2772.